Safe Subclassing in Win32(Win32中的安全子类化)

掌握窗口信息函数,增强Delphi程序能力 本文深入探讨了Delphi中窗口信息函数的使用,特别是GetWindowLong和SetWindowLong函数的高级应用。文章详细介绍了如何通过这些函数获取和设置窗口的用户数据、子类窗口以及枚举系统中所有窗口的详细信息,使开发者能够更加灵活地操作窗口,增强程序功能。 阅读详情

Safe Subclassing in Win32(Win32中的安全子类化)
Kyle Marsh
Microsoft Developer Network Technology Group
Created: January 25, 1994
译者:BBE&BFE

大意
    这篇文章描述了Win32®环境下的子类化(subclassing)技术,它怎样实现,以及为了使子类化安全而必须遵循的规则(rules)。整篇文章覆盖了实例(instance)子类化和全局(global)子类化。超类化(superclassing)被描述为全局子类化的一个可选(alternative)部分。

    子类化从Win16到Win32没有发生显著的(dramatically)变化。但是在Win32中有些新的子类化规则应用程序必须遵循。其中最重要的(也是最显而易见的)是一个application不能子类化一个属于其他进程的窗口和类。这个规则不能被打破,但这里有某些workarounds(这个词不会翻译)应用程序可以使用。

1.Subclassing的定义
    子类化是一种允许一个application截获送往其他窗口的消息的技术。一个application可以通过截获供其他窗口使用的消息来增加,监视,或者修改一个窗口的默认行为(behavior)。子类化对于改变或扩展一个窗口的行为是一种快捷高效的方法,而你并不需要重新开发这个窗口。子类化默认的控件窗口类(按钮控件,编辑控件,列表控件,组合框控件,静态控件和滚动条控件)是一种获得控件的功能并修改它的行为的方便方法。例如,如果一个多行(multiline)编辑控件包含在一个对话框中,并且用户按下了ENTER键,则对话框将被关闭。通过子类化这个编辑控件,当用户按下ENTER键时,一个程序可以插入一个回车符号并且文本换行而对话框没有退出。为了一个应用程序的这个需要,通过子类化技术,并不需要重新开发一个编辑控件。

2.基础
    创建一个窗口的第一步就是填充WNDCLASS 结构并调用RegisterClass函数注册(register)一个窗口类。WNDCLASS结构的;一个元素就是窗口过程(window procedure)的地址。当一个窗口被创建,32位版本的微软Windows™操作系统就读取WNDCLASS结构中的窗口过程地址并且拷贝其到新窗口的信息结构(information structure)。当一个消息被发送给该窗口,Windows通过保存在窗口的信息结构中的地址调用相应的窗口过程。要子类化一个窗口,你可以通过用新的窗口过程地址替换原来的窗口过程地址来使一个新的窗口过程接收发送给原始窗口的所有消息。
    当一个应用程序子类化了一个窗口,它可以对消息执行三种动作:(1)传递这个消息到原始窗口过程;(2)修改这个消息并传递它到原始窗口过程;(3)不继续传送该消息。
     一个子类化了一个窗口的应用程序可以决定什么时候对它接收到的消息作出反应。这个程序可以在发送该消息到原始窗口过程之前或者之后,或者之前并且之后处理该消息(The application can process the message before, after or both before and after passing the message to the original window procedure.)

3.Types of Subclassing子类化的类型
    子类化有两种类型,分别使实例子类化(instance subclassing)和全局子类化(global subclassing)
    例子类化是指子类化一个独立窗口的信息结构。使用实例子类化,只有特定窗口实例的消息会被发送到新的窗口过程(it only substitutes the address of window procedure in the window’s information structure, not WNDCLASS structure. We can see from the Topic “The Basics”,each window has its own information structure.)
    全局子类化是指替换一个窗口类的WNDCLASS结构中的窗口过程地址.所有后来被创建的这种窗口类的窗口拥有被替换了的窗口过程地址。全局子类化只对子类化发生后创建的窗口有影响。在子类化时,如果任何该窗口类的窗口已经存在,则存在的窗口不受全局子类化的影响。如果程序需要影响已经存在的窗口的行为,这个程序必须子类化每个存在的该窗口类的实例。

4.Win32 子类化规则
    在Win32中,有两种子类化规则适(应)用于(apply to)实例和全局子类化。
    子类化只允许在一个进程中发生,一个程序不能子类化属于另一个进程的窗口或类。
这条规则的原因很简单:Win32进程拥有独立的地址空间。一个窗口过程拥有其自己的地址。在一个不同的进程,窗口进程拥有不同的地址。作为结果,从一个进程中替换一个来自另一个进程的地址不能带来期望的结果,所以32位版本的Windows不允许这种替换发生(也就是说(that is),从一个不同的进程中进行子类化)。SetWindowLong和SetClassLong函数不允许这种类型的子类化。你不能子类化其他进程中的窗口或者类。
    然而,仍然有某些方法可以使你能对任何进程增加子类化功能。一旦你得到一个进程的地址空间内的一个函数,你可以子类化该进程的任何部分。有少数几个方法可以达到这个目的。最简单(也使最无礼的)方法(approach)是向注册表的下面这个主键添加一个DLL(Dynamic-link library)的名字。HKEY_LOCAL_MACHINE/Software/Microsoft/Windows NT/ CurrentVersion/Windows/APPINIT_DLLS
    这个主键导致Windows添加你的DLL到系统中的所有进程。在任何你的DLL想要子类化的事件发生后,你的DLL可能需要某种方法唤醒。WH_CBT钩子通常可以做到这点。DLL可以监视HCBT_CREATEWND事件,然后子类化期望的窗口。CTL3D例子程序使用WH_CBT钩子来进行子类化,不过它没有包含子类化任何进程的注册表入口。应用程序想要实现CTL3D的可以链接它到自己的进程中。
    另一种添加你的子类化代码(subclassing code)到任意进程的方法是使用一个系统范围的钩子。当一个系统范围的钩子被从另一进程的上下文中调用,系统就把包含这个钩子的DLL载入该进程。CTL3D代码以同本地WH_CBT钩子同样的方式处理系统范围的WH_CBT钩子(In fact we called them global hook and thread-specific hook) 。
    第三中方法非常复杂:它包括使用OpenProcess, WriteProcessMemory, and CreateRemoteThread函数来向其他进程注入代码。我不推荐这种方法,也不想详细讨论怎么实现它。对于坚持想用这种方法的开发人员,Jeffrey Richter(我最崇拜的Windows编程大师,技术作家,《windows核心编程》的作者)告诉我他正打算在他最近的在Microsoft Systems Journal 中的Win32 Q&A(Questions and Answers)专栏中描述这个技术。
    今天,许多Windows 3.1程序子类化其他进程来增强该进程并增加某些非常酷的功能。Windows正向面向对象系统发展,对象链接和嵌入(OLE)提供了一个实现该功能更好的方法。在未来版本的Windows中,子类化其他进程可能会变得更难,而使用OLE可能变得更容易。如果可能,我推荐你将你的程序转换为OLE,而不是子类化其他进程。子类化的进程可能不直接使用原始的窗口进程。
    在Win16时代,一个程序可以直接通过 SetWindowLong or SetClassLong的返回值来调用原始的窗口过程。毕竟,这两个函数的返回值就是一个函数指针,所以为什么不直接调用它?在Win32时代,这是绝对不能做的事(definitive no-no). 从SetWindowLong and GetClassLong返回的值可能根本就不是指向之前的窗口过程的地址的指针。这发生在Window NT™中,当一个应用程序用一个非Unicode的窗口过程子类化一个Unicode™窗口,或者说一个拥有Unicode窗口过程的非Unicode窗口。在这种情况下,操作系统必须为窗口接收的消息执行一个Unicode和ANSI之间的转换。如果一个程序使用指向结构的指针调用窗口过程,程序将立即产生一个异常。使用从SetWindowLong or SetClassLong返回的值调用窗口过程的唯一方法就是把该返回值作为一个参数传给CallWindowProc。

5.实例子类化(subclassing a window)
    SetWindowLong 用来子类化一个窗口实例。程序必须拥有子类华函数(subclass function)的地址。子类化函数是指从窗口接收消息并传递给原始窗口过程的函数。子类化函数必须被导出到程序或DLL的模块定义文件中(The subclass function must be exported in the application's or the DLL's module definition file.).
    想要子类化某个窗口的程序使用该窗口的句柄,GWL_WNDPROC选项(在WINDOWS.H中定义), 新的子类化函数地址来调用SetWindowLong函数。SetWindowLong 返回一个DWORD值,这是该窗口的原始窗口过程的地址。程序必须保存这个地址来传递截获的消息给原始窗口过程并且用来从该窗口中移除子类化。通过使用原始窗口过程的地址和窗口消息中的hWnd, Message, wParam, lParam参数来调用CallWindowProc ,程序可以将消息发送给原始的窗口过程。通常,程序只简单的传送它从Windows接收到的参数给CallWindowProc.
    程序同样需要原始窗口过程地址来从窗口移除子类化。程序通过再次调用SetWindowLong 来从窗口移除子类化。程序传递原始窗口过程地址,GWL_WNDPROC 选项和被子类化的窗口句柄句柄给SetWindowLong 函数。
    下面的代码例子子类化一个编辑控件(edit control)并在之后移除子类化。

LONG FAR PASCAL SubClassFunc(HWND hWnd,UINT Message,WPARAM wParam,LONG lParam);
FARPROC lpfnOldWndProc;
HWND hEditWnd;
//
// Create an edit control and subclass it.
// The details of this particular edit control are not important.
//
hEditWnd = CreateWindow("EDIT", "EDIT Test",
                        WS_CHILD | WS_VISIBLE | WS_BORDER ,
                        0, 0, 50, 50,
                        hWndMain,
                        NULL,
                        hInst,
                        NULL);
//
// Now subclass the window that was just created.
//
lpfnOldWndProc = (FARPROC)SetWindowLong(hEditWnd,
                                        GWL_WNDPROC,
                                        (DWORD) SubClassFunc);
.
.
.
//
// Remove the subclass for the edit control.
//
SetWindowLong(hEditWnd, GWL_WNDPROC, (DWORD) lpfnOldWndProc);
 
//
// Here is a sample subclass function.
//
LONG FAR PASCAL SubClassFunc(HWND hWnd,
                             UINT Message,
                             WPARAM wParam,
                             LONG lParam)
{
   //
   // When the focus is in an edit control inside a dialog box, the
   //  default ENTER key action will not occur.
   //
 //
   if ( Message == WM_GETDLGCODE )
       return DLGC_WANTALLKEYS;//The application will process all keyboard inputs itself.
   return CallWindowProc(lpfnOldWndProc, hWnd, Message, wParam,lParam);
}
    Potential pitfalls潜在的缺陷
    实例子类化普通情况下是安全的,但注意下面的规则可以确保安全。

     当子类化一个窗口,你必须知道由谁来对该窗口的行为负责。例如,Windows对它提供的所有控件负责,而程序对它所定义的所有窗口负责。子类化可对同一进程中的任意窗口进行,然而,当一个程序对一个它不负责的窗口进行子类化,这个程序必须保证子类化函数不会破坏该窗口的原始行为(original behavior)。因为这个程序并不控制该窗口,所以不能依赖于任何关于该窗口的信息,因为对该窗口负责的组件可能在未来改变。一个子类化函数不应该使用窗口中的额外窗口字节(extra window bytes)和类字节(class bytes),除非它确切了解这些字节的含义和原始窗口过程如何使用它们。即使这个程序对额外窗口字节和类字节很了解,它也不应该使用它们,除非该程序决定更新(update)这个窗口并改变这些额外字节的某些方面,否则子类化过程很有可能失败。因为这个原因,Microsoft建议你不要子类化控件类(control classes).Windows对它提供的控件负责,而控件的某些方面可能随着Windows版本的改变而改变。如果你的程序必须子类化一个Windows提供的控件,当新的Windows版本发布(release)时,你也许得更新你的代码。
    因为实例子类化(instance subclassing)发生在窗口被创建后,子类化窗口的程序不能向该窗口增加任何额外字节(extra bytes)。程序应该将需要存储的数据放在被子类化的窗口的属性列表中(property list)。
    可以设置一个窗口的属性。程序使用窗口句柄,一个标识属性的字符串,以及一个指向数据的句柄来调用SetProp 函数。指向数据的句柄通常通过调用LocalAlloc or GlobalAlloc 来得到。当一个程序需要使用窗口的属性列表中的数据,它可以用该窗口的句柄以及标识该属性的字符串作为参数来调用GetProp 函数。GetProp 返回由SetProp设置的指向数据的句柄,当程序使用完这些数据,或者当窗口即将被销毁,程序必须调用RemoveProp 来从窗口的属性列表中移除这些属性,参数是窗口的句柄和属性的字符串标识。RemoveProp 返回数据的句柄,此时程序用这些句柄来调用LocalFree or GlobalFree以释放内存。
     如果一个程序子类化一个已经子类化了的窗口,则移除子类化时必须以相反的顺序进行,即后子类化的先移除。

6.全局子类化(Subclassing a window class)
    全局子类化与实例子类化相似。程序调用SetClassLong 来全局的子类化一个窗口类(window class)。与实例子类化一样,程序需要子类化函数的地址,并且子类化函数必须在程序或DLL的模块定义文件中导出。
    要全局子类化一个窗口类,程序必须拥有该窗口类的一个窗口的句柄。要得到期望的窗口类的窗口句柄,多数程序建立一个相应类的窗口。当程序要移除子类化,它需要一个指向它子类化了的窗口类的窗口句柄,因此,为此目的建立并维护一个窗口是最好的技术(technique)。如果程序建立一个它想子类化的类的窗口,一般会把该窗口隐藏。在得到正确的窗口类的窗口句柄后,程序用该窗口句柄,GCL_WNDPROC 选项(defined in WINDOWS.H),以及子类化函数的地址来调用SetClassLong. SetClassLong 返回一个DWORD值,这是该窗口类的原始窗口过程地址。此时通过调用CallWindowProc,程序可以将消息发送给原始窗口过程。程序可以通过再次调用SetClassLong移除子类化,只需要向开始那样,只是把子类化函数地址换成原始窗口过程地址。

The following code globally subclasses and removes a subclass to an edit control:

LONG FAR PASCAL SubClassFunc(HWND hWnd,UINT Message,WORD wParam,
      LONG lParam);
FARPROC lpfnOldClassWndProc;
HWND hEditWnd;
 
//
// Create an edit control and subclass it.
// Notice that the edit control is not visible.
// Other details of this particular edit control are not important.
//
hEditWnd = CreateWindow("EDIT", "EDIT Test",
                        WS_CHILD,
                        0, 0, 50, 50,
                        hWndMain,
                        NULL,
                        hInst,
                        NULL);
lpfnOldClassWndProc = (FARPROC)SetClassLong(hEditWnd, GCL_WNDPROC, (DWORD) SubClassFunc);
.
.
.
//
// To remove the subclass:
//
SetClassLong(hEditWnd, GWL_WNDPROC, (DWORD) lpfnOldClassWndProc);
DestroyWindow(hEditWnd);
    潜在的缺陷
    全局子类化和实例子类化拥有一样。程序不应该尝试(attempt to)使用窗口类或窗口的额外字节(extra bytes)。除非它确切(exactly)知道原始过程怎样使用它们。如果必须在窗口上附着数据,应该向实例子类化那样使用窗口属性列表。
    在Win32中,全局子类化不影响其他进程的类或之前从这些窗口类建立的窗口。这是从Win16环境过来的非常重要的一个变化。Windows为系统中每个不同的Win32进程保持单独的窗口类信息。要想了解Windows这方面的细节,请参阅MSDN库中"Window Classes in Win32"技术文章。现在全局子类化不会影响其他进程,这成为了开发者有用的技术。在Win16中,全局子类化不被鼓励使用,因为它影响了子类化的窗口类的所有窗口-不光是执行子类化的程序,而是整个系统。这不是程序通常想要的,所以程序只能使用不方便和并不强大(less powerful)的方法来改变系统类创建的窗口的行为。在Win32中使用全局子类化变得非常的简单。

7.Superclassing超类化
   Subclassing a window class causes messages meant for the window procedure to be sent to the subclass function. The subclass function then passes the message to the original window procedure. Superclassing (also known as class cloning) creates a new window class. The new window class uses the window procedure from an existing class to give the new class the functionality of the existing class. The superclass is based on some other window class, known as the base class. Frequently the base class is a Windows-supplied control class, but it can be any window class.
    子类化一个窗口类导致到窗口过程的消息被发送到子类化函数(subclass function)。子类化函数然后把该消息传递给原始窗口过程。超类化Superclassing(also known as class cloning)建立一个新的窗口类。新的窗口类使用存在的类的窗口过程,来使新的窗口类具有存在的类的功能(functionality)。超类化使基于其他的窗口类的,已经存在的类被称为base class。
   Note:Do not superclass the scroll bar control class because Windows uses the class name to produce the correct behavior for scroll bars.
    注意:不要超类化滚动条(scroll bar)控件类,因为Windows使用该类的名字来正确的处理滚动条的行为。
   The superclass has its own window procedure, the superclass procedure, which can take the same actions a subclass procedure can. The superclass procedure can take three actions with the message: (1) pass the message directly to the original window procedure; (2) modify the message before passing it to the original window procedure; (3) not pass the message. The superclass can react to the message before, after, or both before and after passing the message to the original window procedure.超类化拥有它自己的窗口过程,超类化过程(the superclass procedure).
    可以拥有与子类化过程(subclass procedure)相同的行为。超类化过程对消息可以执行三种行为:(1)直接传递消息到原始窗口过程;(2)在传递消息到原始窗口过程之前修改消息;(3)不传递消息。超类化可以在传递消息到原始窗口过程前,后,或之前并之后对消息作出响应。
   Unlike a subclass procedure, a superclass procedure receives create (WM_NCCREATE, WM_CREATE, and so on) messages from Windows. The superclass procedure can process these messages, but it must also pass these messages to the original base-class window procedure so that the base-class window procedure can initialize.
    不象子类化过程,一个超类化过程接收创建消息(create message just like WM_NCCREATE, WM_CREATE, and so on). 超类化过程可以处理这些消息,但它必须传递这些消息到基类(base-class)窗口过程以便于基类窗口过程可以进行初始化。
   The application calls GetClassInfo to base a superclass on a base class. GetClassInfo fills a WNDCLASS structure with the values from the base class's WNDCLASS structure. The application that is superclassing the base class then sets the hInstance field of the WNDCLASS structure to the instance handle of the application. The application must also set the WNDCLASS structure's lpszClassName field to the name it wants to give this superclass. If the base class has a menu, the application superclassing the base class must supply a new menu that has the same menu IDs as the base class's menu. If the superclass intends to process the WM_COMMAND message and not pass the message to the base class's window procedure, the menu does not have to have corresponding IDs. GetClassInfo does not return the lpszMenuName, lpszClassName, or hInstance field of the WNDCLASS structure.
   The last field that must be set in the superclass's WNDCLASS structure is the lpfnWndProc field. GetClassInfo fills this field with the original class window procedure. The application must save this address so that it can pass messages to the original window procedure with a call to CallWindowProc. The application must put the address of its subclass function into the WNDCLASS structure. This address is not a procedure-instance address because RegisterClass gets the procedure-instance address. The application can modify any other fields in the WNDCLASS structure to suit the application's needs.
   The application can add to both the extra class bytes and the extra window bytes because it is registering a new class. The application must follow two rules when doing this: (1) the original extra bytes for both the class and the window must not be touched by the superclass for the same reasons that an instance subclass or a global subclass should not touch these extra bytes; (2) if the application adds extra bytes to either the class or the window instance for the application's own use, it must always reference these extra bytes relative to the number of extra bytes used by the original base class. Because the number of bytes used by the base class may be different from one version of the base class to the next, the starting offset for the superclass's own extra bytes is also different from one version of the base class to the next.
   After the WNDCLASS structure is filled, the application calls RegisterClass to register the new window class. Windows of this class can now be created and used.
   Applications often used superclassing in Win16 because global subclassing was discouraged. Now that global subclassing is no longer discouraged in Win32, superclassing has lost some of its appeal. You may still find it useful to create a superclass if your application wants to change the behavior for only a subset of the windows (instead of all windows) created from a system class, which is the effect of global subclassing.
   Summing Up
   Subclassing is a powerful technique that has not changed significantly in Win32. The only major change is that you can no longer subclass a window or class that belongs to another process. Although there are workarounds for this restriction, I recommend that you move your application to OLE rather than relying on subclassing if you need this capability. 

Delphi窗体继承实践指南 继承是面向对象编程中一个非常重要的概念,它允许程序员在不同的类之间共享和复用代码。在Delphi中,窗体继承的概念可以帮助我们构建出具有相似功能但细节有所不同的多个窗体。通过继承,我们可以在基类窗体中实现通用的界面和行为,然后在派生窗体中添加特定的功能或者定制界面,这样可以大大减少重复代码的编写,提高开发效率和程序的可维护性。继承的目的不仅限于代码复用,还包括了维护一致性和可扩展性。例如,当我们需要更新基类中实现的通用功能时,所有继承了这个基类的派生窗体都会自动获得这些更新,无需单独修改每一个窗体。 阅读详情

相关推荐

win32 汇编 控件子类(源代码)

win32 汇编 控件子类(源代码)

MFC窗口子类

某些时候我们需要改变窗口的默认行为,就需要改变窗口过程(子类窗口),总结了以下三种方法,欢迎讨论。 1)最简单的方法,可以通过传递GWL_WNDPROC调用SetWindowLong来改变窗口过程,可是这个函数还需要窗口句柄作为参数,而句柄只有在窗口创建成功后才合法,所以这种做法只能当不用改变默认WM_CREATE行为(以及一些窗口创建过程中的动作)的时候才适用。 2)窗...

weixin_30673611的博客 195

Win32的窗口子类演示代码

Win32的窗口子类演示代码,演示编辑框限制输入小数、超级链接功能等。

Delphi中的窗口子类技术

(转自http://blog.csdn.net/linzhengqun/archive/2005/11/14/529300.aspx) Windows内部预定义了一些通用的控件,我们在用这些控件的时候不必再调用RegisterClass注册一个窗口类,只要直接调用CreateWindows,并指定一个预定义的窗口类就可以,比如,我们要创建一个Button,只要用如下形式即可: CreateWin

hexiaomin_1984的专栏 814

超类(Superclass)和子类(Subclass

窗口(windowing)实现形式有超类(Superclass)和子类(Subclass),下面一探究竟···子类 Subclass子类是在窗口实例创建之后,把其窗口过程设置为另一个用户定义窗口类的窗口过程函数,从而改变窗口行为。定义用户定义窗口即窗口子类函数的调用者定义为子类窗口,而窗口实例所对应的窗口类为超类窗口。下面分析这一过程。template BOOL C

Wendysuly的专栏 3085

DirectUI笔记(一)窗口子类

在看DirectUI的代码,尝试着写一些理解,可能有误,同时也不知道能写多少。写到哪算哪吧。 先谈谈窗口的子类。 什么是DirectUI呢? DirectUI界面库取名自微软的一个窗口类名“DirectUIHWND”,意为Paint on parent dc directly。即子窗口不以窗口句柄的形式创建,只是逻辑上的窗口,绘制在父窗口之上。这个父窗口就是使用window

Marcelxx的专栏 1671

浅谈VB6.0使用子类

基础知识:Windows的消息驱动机制     子类,对于各位高手来说easy到不得了了,不用我说,基本可以绕路了。但是对于一些新手来说确实很陌生的,基本上在网上也没有什么系统的资料。那么,我就趁着有空余的时间,将自己掌握的一些子类的基本思路,概念介绍给大家。     要说子类,就必须先简单介绍一下操作系统Windows的工作方式。打个比方吧:     “你和我需要交流,那么一种古老的

几罗星人的专栏 6534

TabBars代码解读之——Tabbar栏与其他窗口之间的关系

输入您的搜索字词 提交搜索表单 集成开发环境中各个窗口的行为都是事先实现的,比如,文档编辑窗口对应着多文档类的视图窗口,负责对用户的输入进行响应,更新窗口的内容,主窗口负责调度各个视图窗口。V

oRbIt 的专栏 3733

Win32安全子类

关于子类的话题虽然有些旧,但它至今仍然不失为一种开发Windows的强有力技术,在MFC的内核、甚至.NET的内核中都离不开它,希望本连载能对Windows开发的爱好者有所帮助。 原文标题:Safe Subclassing in Win32 作者:Kyle Marsh MSDN技术组 点击此处查看原文 摘要 本文描述了Win32环境下的子类,描述了它是如何工作的以及

huasonl room 2776

win32中使用SetWindowSubclass阻止Enter键

使用阻止Enter键的编辑控件的简单子类来完成此操作: LRESULT CALLBACK EditSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { if (uMsg == WM_CHAR && wPar...

qq_39529180的博客 139

解说Win32的窗口子类

也许你需要一个特殊的Edit来限制浮点数的输入,但是现有的Edit却并不能完成这项工作——因为它只能够单纯的限制大小写或者纯数字。当你在论坛上求救的时候,某个网友告诉你:“用子类。”你也许会在看到一线曙光的同时多出了一连串的问题:何为子类子类的原理是什么?如何实现子类?下面就让我从一个简单的C++程序开始,一步步解开你的疑团吧。  首先,我为你列出以下这个C++程序:#include

清清湖水 1125

精通Win32 API编程-Windows图形界面编程

Windows的API(Application Programming Interface,应用程序编程接口),是Windows 操作系统提供给应用程序的大量函数,学习本课程,不仅可以掌握Windows界面编程,开发华丽的Windows桌面运用程序,也可以为MFC框架的学习奠定扎实的基础,同时是否熟练的掌握Windows API开发,也是企业考量优秀程序员一个非常重要的指标!

眼见为实(2):介绍Windows的窗口、消息、子类和超类

眼见为实(2):介绍Windows的窗口、消息、子类和超类 这篇文章本来只是想介绍一下子类和超类这两个比较“生僻”的名词。为了叙述的完整性而讨论了Windows的窗口和消息,也简要讨论了进程和线程。子类Subclassing)和超类(Superclassing)是伴随Windows窗口机制而产生的两个复用代码的方法。不要把“子类、超类”与面向对象语言中的派生类、基类混淆起来。“...

技术代码资料库 404

WIN32汇编: 20.窗口子类

第二十课 窗口子类在这一讲,我们将学习什么是窗口子类和怎样按你所想要的方式方便地使用它。理论:如果你曾经在 Windows 环境下编过程序,有时候就会发现:有一个现成的窗口,几乎有你所需要的全部功能,但还不完全一样(否则就没有必要讲这一节了)。你曾遇到过这样的处境吗,如果你需要一个具有过滤特殊字符功能的 Edit 控件。当然最直接的方法就是自己用代码来实现,但这的确是一个费

GodDragon的专栏 2258

Win32子类与超类

大家都知道,MS提供了很多丰富的控件(也叫窗体),但有些控件在实际的应用中可能还是不能满足要求,比如说,我想让BUTTON点击时变成另一种外观,我们怎么做呢?要改变外观就只能重新进行绘制,肯定就需要在HWND的WM_PAINT消息里面处理,问题是我们怎么才能得到这个HWND的消息呢?每一个窗体都是通过CreateWindow来创建的,在创建之前,都会注册一个类,这个类就相当于是模板,当然有些是系统

永远即等待的专栏 2741

SubClassWindow详解

许多Windows程序员都是跳过SDK直接进行RAD开发工具[或VC,我想VC应不属于RAD]的学习,有些人可能对子类机制比较陌生。 我们先看看什么是Windows子类Windows给我们或是说给它自己定义了许多丰富的通用控件,如:Edit、ComboBox 、ListBox……等,这些控件功能丰富,能为我们开发工作带来极大方面,试想:我们单单是自己实现一个EDIT控件是多么的艰难!但

sunliangyuan的专栏 1万+

【转】解说Win32的窗口子类

【转】解说Win32的窗口子类

code09的专栏 517

介绍Windows的窗口、消息、子类和超类

这篇文章本来只是想介绍一下子类和超类这两个比较“生僻”的名词。为了叙述的完整性而讨论了Windows的窗口和消息,也简要讨论了进程和线程。子类Subclassing)和超类(Superclassing)是伴随Windows窗口机制而产生的两个复用代码的方法。不要把“子类、超类”与面向对象语言中的派生类、基类混淆起来。“子类、超类中的“类”是指Windows的窗口类。

899
上一篇: WIN XP操作系统中任意进程的函数挂钩 ----API HOOK 之菜鸟篇
下一篇: VC++下命名管道编程的原理及实现
Y___Y
博客等级 码龄20年 63粉丝 61原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值