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.
Related
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.
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.
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.
Here's the scenario:
-COM DLL, loaded into the address space of the process that uses the DLL.
-Inside the DLL couple global variables exist (lets say var a, var b) and a global function.
-Process starts up, calls the global function and initializes globals a, b and calls CoInitialize(NULL) - The thread is an STA.
-Then same global function creates an STA COM object
Later in the program, same thread (the thread that called CoInitialize above and created STA COM object) calls same global C-Function (lets call it func()) in this DLL. In the scope of the C-function the state of the global variables is exactly as expected (ie. correctly initialized).
The minute the function func() invokes a COM method on the existing STA COM object, the COM object being in the same DLL sees completely different copies of the global variables (var a, var b). I took the address of both variables and they are completely different in the C-func as opposed to invoked COM objects function.
What is going on? I thought globals in same address space should be visible across the board.
It's possible that two instances of your DLL are being loaded -- one explicitly by the application that hosts your DLL, and the second through the COM subsystem via CoCreateInstance. The former will look in the DLL search path for the application's process, while the latter will look in the registry for the location of the COM component that implements your COCLASS.
If your DLL has a DllMain (or the InitInstance function if it's an MFC-based DLL), then you can breakpoint it and look at the hinstance argument (or AfxGetInstanceHandle if MFC) to see if (a) you initialize twice and (b) you see two different DLL instance handles. If so, then you're definitely loading twice.
The DLL's location in the file system matters, so you should see if there are copies in separate locations that might be separately loaded based on the rules I mentioned above.
In general, a COM DLL should never be loaded directly. You should break your functionality up into two DLLs, with a COM server DLL dedicated to the COM stuff. You can provide yourself an internal COCLASS interface that will enable you to pass your globals to the COM DLL, if you so wish.
i have an object A which should be notified (A::Notify() method) when some thread starts or dies.
Lets say this thread dynamically loads some DLL file of mine (i can write it).
I believe i should write the dllMain function of this DLL, however i'm not sure how to get a reference to the A object from this function so i can run it's Notify() method.
any ideas?
A DLL is loaded once in every process. Once loaded, its DllMain is automatically called whenever a thread is created in the process. Assuming A is a global variable, you can do the following:
After you first load the DLL, call an exported function that will set a global pointer to A in the DLL
Whenever DllMain is called with the reason being thread attached, call A via the pointer you have in the DLL.
Another option would be to start a message loop in your exe, and pass it's thread ID to the DLL. Then, whenever a thread attaches to the DLL send the message loop a message with the details of the created thread. This is a slightly more complicated solution, but it will save you the need of making the DLL familiar with the A class.
Is it okay to make A::Notify() as static method?
Otherwise, Singleton method might serve the purpose.
So if I understand you write, in your main program you have an instance of class A. When your main program loads certain dlls you want it to call A::Notify for that instance?
As far as I'm aware there is no way to pass an additional argument to LoadLibrary.
If A::Notify can be either static, or A is a singleton, export a "NotifyA" method from the exe, then have the dll call LoadLibrary("yourexe") and you GetProcAddress to get the address of NotifyA which you can then call. (Yes exe files can export methods like dlls!)
A second option is to write your own LoadLibrary, that call a second method after dll main, eg
HMODULE MyLoadLibrary(string dll, A *a)
{
HMODULE module = LoadLibrary(dll.c_str())
void (call*)(A*) = void (*)(A*)GetProcAddress(module, "Init");
call(a);
return module;
}
The dlls Init method can then store the A instance for later.