According to msdn, when I get a CWnd* with CWnd::FromHandle,
The pointer may be temporary and should not be stored for later use.
What is meant by "later use" is not clear to me. Is it only the scope of the current method?
As far as I know, there is no GC in Win32!
MFC maintains a number of handle maps, from HWND to CWnd, HDC to CDC etc, which are stored in the thread state. Each handle map contains a permanent map and temporary map - permanent entries are added when you call a method such as CWnd::Create or CDC::Attach, while temporary entries are created when you call FromHandle on a handle that doesn't have a permanent entry.
Temporary entries are cleaned up during idle processing (in CWinApp::OnIdle), so they can only safely be used while processing the current message. As soon as you return to the message loop, or enter another modal loop (e.g. by calling DoModal) then they may be deleted.
FromHandle is basically used for getting a transient reference to an already existing window object. MFC stores these references in an internal structure called a temporary handle map (a handle map is a map of Windows HWNDs to MFC CWnd objects used by MFC to make Win32 calls to manipulate the actual Windows window the MFC object corresponds to). In order to avoid the number of objects in this structure from growing beyond all bounds, items are deleted from the handle map during MFC's idle loop processing.
As you may have guessed, there is also a permanent handle map that won't have this automatic clean up behavior. If you need to get a CWnd object that doesn't put its HWND reference in the temporary handle map you can call FromHandlePermanent().
-Ron
Based on the same MSDN description, I would assume that this means that if no CWnd is attached to the hWnd provided as an object, it will create a temporary CWnd which probably gets destroyed once something goes out of scope, or a destructor elsewhere is called, or a CWnd is explicitly created for the hWnd in question. So if you already have a CWnd created, you should be OK, otherwise you will probably need to be very careful with storing the pointer you receive.
Typically they only want you to use this handle with in the scope of your function. And not to store it as a class field where you reference it through out the life of your object.
Related
I'm writing a small MFC app and loading an icon handle like this in my executable upon launch:
const HANDLE hIconLarge = ::LoadImage(AfxGetInstanceHandle()
MAKEINTRESOURCE(IDI_EXAMPLE), IMAGE_ICON,
::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), 0);
I am retaining this same handle in another class in a DLL I created by simply assigning it like this:
m_hLargeWindowIcon = p_hLargeIconHandle;
where m_hLargeWindowIcon is a private class HANDLE variable in a singleton that I call IconManager. I then later occasionally use this icon handle to set the large icon for pop-up windows that my DLL creates.
It seems to be working fine, but I am concerned about the life cycle of the handle I am retaining.
Is it safe to save a handle in this fashion (i.e. the handle will remain valid until the host process of my DLL is terminated) or can I run into issues where the handle may not be valid when I access it at a later point in time? Should I be using DuplicateHandle or something to that nature in this case?
You don't need to duplicate the handle in any way. Your usage is fine, apart from the fact that you are using the wrong type. Instead of HANDLE you should use HICON.
When nothing more refers to that icon handle, you do need to destroy it. Call DestroyIcon to do so.
The lifetime of the icon is as long as a valid handle to it (HICON) exists, else, it'll get cleaned up when the process exits.
Normally you would want to wrap the functionality up in a Icon class of some sort with appropriate copy and move semantics. Or at the very least tie it to a RAII class to manage the lifetime of the HICON.
Given the singleton nature of its use here, that may be overkill. Let the singleton clean it up DestroyIcon when the program exits. One caveat here is that you really should be sure that clients of the code don't try clean it up for you. Once they have a bit copy, sure, there is little you can do to stop them, but at least be clear in the documentation how the code behaves and some reason as to why (since this seems to be a corner case w.r.t. the resource management).
Side note: I believe the correct function to duplicate an icon is CopyIcon.
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.
I have a legacy code. The code works like this: after an Event1 has happened it creates an window object ( inherited from CWindowImpl class ) in the heap. After an Event2 has happened it applies changes made in the window, closes it by calling DestroyWindow() and frees the memory in the heap by calling delete.
This code is buggy because it deletes the window object before all the messages for this window are processed. How to know for sure when it's safe to call delete for the window object?
The only solution i found out is to override OnFinalMessage and call delete this there. I don't like it because it must be guaranteed that the object is created in the heap only. Are there better ideas?
Thank you.
Having done DestroyWindow, you have the handle of the window destroyed, so it is safe to use delete on the window class pointer. No late messages can arrive at that point.
OnFinalMessage comes from inner WTL's handler for WM_NCDESTROY message.
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?
Newbie question: I have a forms application. It has a separate thread which makes a web services call, and then posts the results of the call to the main form.
In my thread, after X seconds have passed (using a TTimer), I call:
procedure TPollingThread.OnTimer(Sender: TObject);
var
SystemProbeValues : TCWProbeValues;
begin
SystemProbeValues := Remote.Run.GetSystemProbeValues;
PostMessage( ParentHandle, WM_APIEVENT ,Integer(apiMultiCellStatus), Integer(SystemProbeValues) );
end;
The function Remote.Run.GetSystemProbeValues has the following prototype:
function GetSystemProbeValues : TCWProbeValues; stdcall;
And TCWProbeValues is a dynamic array of TCWProbeValue objects (which all descend from TRemotable).
In my main form, I receive the message just fine and cast the LParam back to TCWProbeValues:
procedure TFrmCWMain.OnAPIEvent(var msg: TMessage);
begin
ProbeValues := TCWProbeValues(msg.LParam);
end;
My question is, given that the dynamic array and its objects were created by the Delphi HTTORIO system, who is responsible for freeing them? Did Delphi consider that memory re-usable after my OnTimer function returned? (And in which case, its pure good luck that my main form message handler can actually read the memory referenced by the LParam of the message?) Or rather, is it my responsibility to free the object auto-instantiated by the HTTPRIO request?
Many thanks, please shout if the above needs more detail / code and I'll add to it!
Cheers, Duncan
TRemotable provides lifetime management via its DataContext property, so the SOAP runtime will free the object itself. As long as the data-context object exists, everything it allocated will exist, too. If you want to claim ownership of and responsibility for an object, simply clear its DataContext property. (That's probably what you'll want to do in this case because your API-event message may get handled after the SOAP event has terminated.)
A problem in your code is that you're passing a dynamic array via a posted message. When your OnTimer procedure returns to its caller, the dynamic array referenced by SystemProbeValues will have its reference count decremented. If the other thread hasn't processed the message yet (and it probably hasn't), then the dynamic array might already be destroyed by the time it does get around to processing that message.
The easy way around that is to clear the reference in the timer's event handler without reducing the reference count, and then do the opposite in the message handler. After you post the message, clear the variable:
LParam(SystemProbeValues) := 0;
In your message handler, clear the old value of the global ProbeValues variable and assign the new value like this:
ProbeValues := nil;
LParam(ProbeValues) := Msg.LParam;
Another problem lurking in your code may be the use of TTimer in a non-VCL thread. That class creates a window handle to share among all instances of the class. Unless your timer thread is the only thread in the program that uses TTimer, you will probably have problems, either with functions running in the wrong thread, or functions not running at all. Instead of TTimer, you can use SetTimer to create an OS timer manually, or you could create a waitable timer, which may be more suitable for use in a thread that doesn't need to remain responsive to user actions.