I would like a literature describing the architecture and interaction of controls with each other on a slightly deeper level than “Here we inherit from UserControl , here we redefine a couple of methods, and this is actually all you need to know.”

For the clarity of the words "architecture" and "interaction", here is a sample list of questions that gnaw at me:

  1. Each control has its own Graphics . And how and in what order do they form a single picture?
  2. When the control wants to redraw itself, who and how does it notify about it?
  3. I heard somewhere about a single event pool for the entire application. How do they crawl to the final controls?
  4. How to kill controls? Simple Dispose() or else delete from parent.Controls ?
  5. Etc.

I would be glad to have a detailed article, but I will not give up the chapters from the book.

    1 answer 1

    If you are really talking about Windows Forms , and not, for example, WPF , then this whole library is just a well-designed wrapper on the WinAPI part for working with visual components.

    Since the topic is quite extensive, in a short answer it will not be possible to tell all this; I suggest you start learning from articles on basic principles of developing window applications and learning the SendMessage function on MSDN .


    Further - specifically on your questions:

    1. Graphics itself doesn’t add up anywhere, it’s just a wrapper over some region of a form drawn using WinAPI . That is, Graphics provides the ability to change the rendering mechanism of a particular control, without affecting the general logic of the drawing itself. Regarding the order - each control has its own z-index , which can be changed, for example, using the Controls.SetChildIndex function and this particular index is taken into account when the form is invalidated.

    2. All messages in WinAPI pass through the so-called Message pump, while anyone can send a message about redrawing. Here, for understanding, you should read the articles about the WM_PAINT message and the invalidation methods - Controls.Invalidate, which in fact is marshall-type methods InvalidateRect.

    3. See (2)

    4. Again, for reasons of using unmanaged code inside managed (when marshalling WinAPI calls), you must release all allocated resources of type HXXRESOURCE , this is implemented in the Dispose method. Since the form is a container for other controls, it is she who is responsible for their release, that is, the Form.Dispose method on the contract should call Dispose methods for all its controls. If this does not happen, then it is bad.

    5. If you are interested, you can study the source code of Windows.Forms and see exactly how everything is implemented in it. Of interest is also an alternative implementation of mono-winforms . I also recommend that you familiarize yourself with the WPF ideology and reflect on the architectural decisions that were made during the development of this library.

    • Thanks for the "basic principles", I read. Further, according to the answers: 1. That is, I correctly understand that there is one big Bitmap (or its analogue) for the whole form, and controls through Graphics given access to its areas? 2. It turns out that a non-overloaded Control.Refresh first calls Redraw on itself, then calls Refresh on all child controls, and the last one throws WM_PAINT into the Message pump? If yes, it is not clear unless, as determined by the latter. - Jofsey
    • @Jofsey 2. Not really. The idea is that one WM_PAINT message will be sent to each control in the message queue, and the sequence of their arrival should correspond to the visible order. In the simplest case of the Message Pump implementation, all the controls would necessarily be redrawn once, “overlapping” each other. But in reality, handling of messages like WM_PAINT is different from processing other messages, since WM_PAINT falls in Pump in large quantities. - Costantino Rupert
    • @Jofsey In general, Message Pump able to group WM_PAINT messages in order not to carry out unnecessary actions and can group them by region (here you need to look at the source codes for details), that is, in the final version, all this set of WM_PAINT messages should be left do not overlap each other and redraw only those areas that really need to be redrawn. - Costantino Rupert
    • one
      2. Each control receives a WM_PAINT message and, in its message handler, passes it into a managed ( C# code) OnPaint handler. 3. There, from PaintEventArgs we can access the Graphics object, and the start of actions with the Graphics object causes the Lock corresponding region of the form, and the ending - Unlock . Working with bitmap as such is present only here and does not extend beyond OnPaint . Overhead costs, about which I spoke, go to the allocation of unmanaged handlers and synchronization. - Costantino Rupert
    • one
      @Jofsey Next - about the WM_PAINT grouping. The idea here is that the Message Pump abstraction itself is more complicated than just "getting the message - processing it." It is asynchronous and is able to perform certain actions in a separate way when WM_PAINT added to the message queue. Since the redrawing is slower than the accumulation of messages, it often happens that, at the moment WM_PAINT "falls" into the queue, there is already a message that is identical to this one, which has not yet been processed. It is clear that in this case a new message can be discard. - Costantino Rupert