Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Windows Class Names and Windows Forms


Windows Class Names and Windows Forms

A Win32 window is created from a registered windows class. The class defines various properties of the window like the cursor and the background color, but the most important piece of information is a pointer to the windows procedure that will handle the messages sent to the window. In effect, the windows procedure defines the behavior of the windows created from the class. Since an application wants to define the behavior of its windows, it means that the application must define its own windows class, and this must be registered with the system before a window can be created.

Standalone Windows Forms windows are always derived from Form or a class derived from it. The behavior of a form is determined by its event handling code. The Form class has the default event handling code to create a pretty useless, but fully functioning, window. To create your own form, you derive from Form and add event handlers to replace the default handlers. Once you have defined a form class, you can add additional functionality by deriving from that class.

Notice that in this description of forms, I have not mentioned registering a windows class. The reason is simple: It is unnecessary because the Windows Forms library will create a single windows class for all the windows in your application (well, application domain, but I will come to that in a moment), and all forms will use this single windows class. This may seem odd, but if you think about it, a form behaves very much like a dialog box, so I shall use dialogs as an analogy. In Windows, all dialogs are created from a single windows class, elegantly named #32770. When CreateDialog() (or one of the variants) creates a dialog, it creates an instance of this class and populates this window’s client area with the controls identified in the dialog template. Now compare this with a form: When a form is created, an instance of the single windows class is created and its client area is populated with the controls identified in your code (usually InitializeComponent(), added for the convenience of the designer). So having a single windows class for all windows is an established procedure for Microsoft.

Somewhere, then, there must be some code that registers a windows class to be used by a form. Form is a child of the Control class, which has most of the code to handle the Win32 windowing. Control has a nested class called ControlNativeWindow, which derives from NativeWindow, which is used to wrap the Win32 window. When you first create a control or a form, no Win32 window is actually created. However, the first time that the control is made visible by calling the Visible setter, a chain of method calls ends up in a call to the CreateHandle() method of NativeWindow. This method is passed a CreateParams class that has default information about the window. Although this class has a property called ClassName, it is not used by Form or Control, and this property has a default value of null. CreateHandle() calls the Win32 native code to create the window upon which the .NET control is based.

However, since the ClassName member of the CreateParams instance is null, this code does not have a windows class name to pass to the Win32 CreateWindowEx(). To get around this issue, NativeWindow has a nested class called WindowClass, CreateHandle() creates an instance of this class, and after various tests are performed eventually another method, WindowClass.RegisterClass(), is called. As the name suggests, this registers a windows class. This windows class uses a windows procedure in NativeWindow that calls Control.WndProc() which ends up in a huge switch that handles Windows messages by raising events (its not quite that simple, but describing the full details of how this method is called would take up too much space).

The windows class is given a name in the form:

<windowsformsversion>.<windowstyle>.app<hexappdomainhash>

where <windowsformsversion> is the version of the library and is a fixed string ‘WindowsForms10’. <windowstyle> is in the form of Window.<hexstyle> where <hexstyle> is the style of the window (see Control.GetStyle()) in hex. Finally, <hexappdomainhash> is the hash code of the current app domain given in hex.

For example, a Form could have a class name like this:

WindowsForms10.Window.8.app1  

Once the class has been registered it is stored in a cache, and this class is used the next time a form is created.

In fact, most Forms will have the class name I have just given; the only bit that will vary is the application domain portion of the name, or (occasionally) the style part. The big problem with this design is that it makes finding a window a pain. Win32 code can use FindWindowEx() to search for a window with a specific class name, and .NET code can call this method through a platform invoke. However, you cannot guarantee what the name will be (because you may not know what the application domain portion will be) and even if you could specify the name, all forms in the application domain will have the same class name regardless of the .NET class that was used to create the form.

In the next newsletter, I will identify a couple of solutions to this issue. I will also point out some other features of Windows Forms that can constrain how Win32 windowing functions and forms interact.


Richard Grimes speaks at conferences and writes extensively on .NET, COM, and COM+. He is the author of Developing Applications with Visual Studio .NET (Addison-Wesley, 2002). If you have comments about this topic, Richard can be reached at [email protected].


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.