WinAPI SetWindowLongPtr - Changing windowProc - c++

On MSDN website, I found following:
Calling SetWindowLongPtr with the GWLP_WNDPROC index creates a
subclass of the window class used to create the window. An application
can subclass a system class, but should not subclass a window class
created by another process. The SetWindowLongPtr function creates the
window subclass by changing the window procedure associated with a
particular window class, causing the system to call the new window
procedure instead of the previous one. An application must pass any
messages not processed by the new window procedure to the previous
window procedure by calling CallWindowProc. This allows the
application to create a chain of window procedures.
Does this mean, that every time I call SetWindowLongPtr with GWLP_WNDPROC, new subclass will be created, or is Windows smart enough to create subclass only once if same procedure is passed multiple times as parameter?

The term "subclass" is conceptual in the winapi. It was originally designed back in 1983 to target the C language. Which does not have any support for classes of course.
1983 was an important year in software development, that's when objected-oriented programming started to take flight. That's when Bjarne Stroustrup renamed his "C with Classes" to C++. And when Xerox released their Smalltalk-80 implementation to anybody who wanted a copy. Given Smalltalk's focus on message passing, it is likely to have been a strong inspiration to the Windows designers.
So while the winapi could not be purely objected-oriented, it certainly got a whiff of the technique. RegisterClass() function is most obvious, acts like a base class that gives any window "object" created from that class the same behavior. The window procedure specified with WNDCLASS.lpfnWndProc acts like a virtual method that can be overridden.
So a "subclass" of the class registered with RegisterClass() merely overrides the lpfnWndProc function. You do that with SetWindowLongPtr(), you have to bring the new function yourself. You do have to call the "base" function like you would commonly do when you override a virtual function in a C++ program.
Not the only way to do it. The SubWindowSubclass() function is a helper function to get it right. The DefSubclassProc() function helps you call the "base class". Recommended.

Related

WM_CREATE and MainWindow

I have seen some examples on the internet where buttons were created under WM_CREATE and I have done some projects where creating "some" buttons such as Start/Stop buttons or Text Fields had to be created under MainWindow and not under WM_CREATE.
Is there any reason for chosing/difference/benefit of the choice of one over other when we can chose between these two?
I don't know anything about the Win32Gui library in particular, but I've used plenty of Win32 wrapper libraries and even written one myself.
Handling the WM_CREATE message (which is sent to a window after it is created) is the typical way of creating dynamic child windows such as button controls. This would be the same regardless of whether you're working directly with the Win32 API or using a wrapper library. The only difference might be how that wrapper library expects you to handle the message. For example, in MFC, you would override a member function of the window class called OnWmCreate.
But you really can create child windows anywhere in the code. You aren't forced to do it in response to WM_CREATE. You could do it in response to WM_KEYDOWN if you wanted. The only requirement is that you must have already created the parent window (because you must pass a valid handle to the parent window when creating the child window).
It sounds to me like the MainWindow you're talking about is the constructor method for your MainWindow class (a C++ object that models a Win32 window). Depending on the design of the framework, this may or may not be a valid place to create child windows. It depends on that above-stated requirement: whether the underlying Win32 window represented by the C++ object has already been created and whether you have a valid handle to it available inside of the constructor body.
Some frameworks implement a two-phase style of construction for window objects. What I mean by that is that the class constructor creates an instance of a C++ object, and then you need to call a second member function (e.g. Create) to create the Win32 window represented by the C++ object. In cases like this, you cannot create child windows inside of the parent window's constructor because the parent window has not yet been created and you do not have a valid handle to use when creating the children.
Other frameworks might require that you specify all of the necessary parameters to create the underlying Win32 window when creating your C++ object, and then the constructor will take care of creating both the C++ object and the underlying Win32 window (e.g. by calling the CreateWindow function). If the creation of either fails, an exception will be thrown. Otherwise, you can be sure that you have access to a valid window handle inside the body of your derived class's constructor.
However, even if this single-phase approach to construction describes the design of your wrapper library, I would still suggest creating child windows in response to the WM_CREATE message, rather than in the constructor. But that's just a personal preference and a matter of individual style.
Different people have different ideas about how much work should be done inside of a constructor. My personal litmus test is that, after the constructor has run, you should have a valid, fully usable object on which any member functions can be called. I don't much care for two-phase construction, because I don't like the interface complexity that introduces of requiring the consumer to not only create the object, but also call a Create or Init method. I don't consider child windows to be an integral part of the parent, though, so I say that their creation belongs elsewhere than in the parent's constructor.
I cannot understand why you say
I have done some projects where creating "some" buttons such as Start/Stop buttons or Text Fields had to be created under MainWindow and not under WM_CREATE.
There is no reason why you would have to create child windows in the constructor and you would be unable or it would not work to do so in response to the WM_CREATE message.

What is the typical convention for organization with Win32?

I've been working a lot with Win32 lately, but I'm pretty new to it, and need some advice concerning organization. In C++, although it works syntactically to declare global variables, I was always under the impression that this was sloppy, because the variable can then be modified anywhere, so it becomes much more difficult to track changes to it.
In my Win32 project, I've got several variables which need to be modified in multiple places. For instance, one such variable was in the WndProc function and also in a dialog procedure function. Due to the way it was used, I was able to simply use the actual values in WndProc, and then call the dialog box using DialogBoxParam, and pass the value to the dialog box through the lParam value.
However, there are other values, such as certain bitmaps that I use for drawing or variables that are used in multiple different window message calls, where the value(s) need to be retained throughout multiple instances of the WndProc function or multiple functions. I can control the parameters of the functions I created, but what if I need to pass a variable into the WndProc function so that I can use it regardless of multiple different window messages? What if I need to pass in multiple values?
So far I've just been making everything global, and it works, but it feels sloppy to me...but I know that some variables are generally global as a matter of convention - like the main window and instance variables.
What do you all think?
It might help if you had a specific example in code. But I think you're talking about lifetime--you have a resource (say a bitmap) and you need to reference it many times in response to different Windows messages. You could make it global, yes, but I agree that's sloppy.
So who created the window? Likely your "App" class or something along those lines. Since that class's lifetime is logically longer than the window's, it could hold the resources required by the window.
Or a better approach is to create a "Window" class. Your App instantiates a Window object. The Window object creates the Win32 window and holds the HWND (you've now abstracted that away from the App so it doesn't need to know those gory details), and the Window instance can hold the bitmap resources.
Instead of using global variables you can store window-specific data in a C++ object associated with the relevant window.
To associate a C++ object with a window, use any of a number of existing C++ class frameworks (such as e.g. Microsoft’ WTL or Torjo's Win32GUI), or do it yourself by using SetWindowSubclass API function.
For the Do It Yourself™ solution, I presented a complete C++ example in another SO answer.
That said, for a tiny little program global variables + a dialog is the easiest and presents no problems. So in general, use the Right Tool™ for the job. For larger jobs, use more heavy tooling…

In MFC DLL Why do I must declare theApp using “CWinApp theApp;”?

In MFC DLL Why do I have to declare theApp using “CWinApp theApp;”,or else it will occur runtime exception. When theApp was instantiated?
[From MSDN]
theApp is the application object. This object is constructed when other C++ global objects are constructed and should be already available when Windows calls the WinMain function. And it is necessary to declare your object at the global level.
[From Programming VisualC++]
Application startup—When the user starts the application, Windows calls the application framework's built-in WinMain function, and WinMain looks for your globally constructed application object of a class derived from CWinApp. Don't forget that in a C++ program global objects are constructed before the main program is executed.
The CMyApp::InitInstance member function—When the WinMain function finds the application object, it calls the virtual InitInstance member function, which makes the calls needed to construct and display the application's main frame window. You must override InitInstance in your derived application class because the CWinApp base class doesn't know what kind of main frame window you want.
The CWinApp::Run member function—The Run function is hidden in the base class, but it dispatches the application's messages to its windows, thus keeping the application running. WinMain calls Run after it calls InitInstance.

In MFC why do I need to create a global instance of CWinApp?

Why the constructor of my derived CWinApp should be invoked before main function starts?
Why can't it be something like:
int WinMain()
{
CMainFrame* pMainFrame = new CMainFrame;
// etc ...
}
I'm looking for the technical reason that forces this behavior.
Edit:
To make clearer - If I'm using win32 API without MFC the main window is created inside WinMain so what is the difference?
Basically, that's because the MFC designers decided to provide the application entry point (WinMain(), not main()) in the library itself, so users would not have to write one.
The application's initialization and termination logic is then relocated to the InitInstance()and ExitInstance() methods of the instance of a user-provided CWinApp-derived singleton. This instance has to exist before WinMain() runs, because it calls the aforementioned methods (and Run() to enter the message loop) and uses it to store state (like the nCmdShow argument it receives).
Defining the CWinApp-derived instance in the global scope is an easy way to ensure it does exist by the time WinMain() runs.
This article has additional details on what happens under the hood when an MFC application starts.

When a window closes, do my destructors get called?

If a window is closed (like with sending WM_CLOSE), are the destructors of objects called?
I followed my source code with a break point in that situation, but the compiler doesn't seem to pass through my destructor.
Is the program closed without calling any destructors?
Normally, not, unless your WindowProc makes it so.
The Window class (e.g. CWnd in ;FC and CWindow in ATL) are distinct entities from the OS' concept of a window (I'll denote as HWND). They have different lifetimes, but they can be "coupled" together using the WNDPROC.
IIRC, MFC will delete CView-derived classes, but not most of the CWindow-derived. Also, ATL's CWindow, by itself won't be destroyed, as it is by default only a one-way attachment (i.e. attaching a CWindow to a HWND usually doesn't subclass the window).
Most of the time, calling the destructor is by another mechanism:
CDialog foo;
foo.DoModal();
When the dialog is closed, the scope where foo is declared will be exited and foos destructor will be called.
Similary, closing the main window will cause the application to exit, tearign down instances on that way.
I'm not too sure I understand, but let's say you've got a window setup with a typical WndProc and you're pumping messages with something akin to:
while (GetMessage(&msg, hwnd, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
When the window finishes (processes WM_DESTROY, after WM_CLOSE posts is handled and called DestroyWindow), this loop will end, and you'll continue normal execution.
In other words, the window isn't anything too special, but while it's up you're pretty much stuck in this loop. You get the same cleanup as always.
It depends on what the program does after the windows is closed. If it exits normally (by returning control from main()) - then yes, the destructors will get called, but only of stack-allocated and global objects. If it calls TerminateProcess() they will definitely not get called.
The objects in Windows (windows, dialogs, controls etc) are separate and distinct from the C++ objects in your program which wrap them. A window or dialog being closed will not delete a C++ object in your program which happens to be associated with it by way of an m_Hwnd member variable.
To put it in MFC terms, think of it this way - if closing a dialog destroyed the CDialog object associated with it, how could you then retrieve the CDialog DDX data associated with the (small d) dialog's controls?