Who is owner of GWLP_USERDATA cell? - windows

good known that GWLP_USERDATA can be used to associate some pointer size data with the specified window. but who has the right do it ? obviously if two piece of code independently do this - one piece is overwrite data of another - so there must only be one owner. but it must be clear determined a general rule - who is owner of GWLP_USERDATA cell ? whom it belong ?
can be two internally consistent agreements:
code that created the window is owner. belong to the creator of the
window
code which implement window class. belong to the window class
implementer
what of this two solutions must be used ?
1. from MSDN:
GWLP_USERDATA:
Sets the user data associated with the window. This data is intended
for use by the application that created the window. Its value is
initially zero.
how need understand This data is intended for use by the application that created the window ?
so code which call CreateWindowEx, CreateDialogParam, DialogBoxParam, etc - and only this code can use GWLP_USERDATA. from this also follows that window class implementer can not use GWLP_USERDATA. so huge number of examples where GWLP_USERDATA used for bind instance of class to the specified window is incorrect. Managing Application State - official MSDN example, where GWLP_USERDATA used for bind data structure to window is incorrect ?!
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
is error under this rule.
what can be said in favor of this version ?
i check different windows versions (from xp to win10) - how i can see all windows built-in window classes ( WC_* and others) use
SetWindowLongPtr(hwnd, 0, (LONG_PTR)pThis);
for bind instance of class to the specified window. always index 0 used instead GWLP_USERDATA
many can say - so what ? even if now this is true, what about future windows versions ?
but if think, what sense migrate from index 0 (really private implementer index in all senses) to GWLP_USERDATA ?
change existing SetWindowLongPtr(hwnd, 0, (LONG_PTR)pThis); to SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis); what prize ? or additional begin use GWLP_USERDATA with index 0 too ? this already absolute senseless - one pointer is enough for bind window to data structure, all additional pointers must be (and in case windows code will be) in this structure already. so i personally can assume that this is not changed
also can note an error in the documentation for SetWindowLongPtr and GetWindowLongPtr here:
The zero-based offset to the value to be set. Valid values are in the
range zero through the number of bytes of extra window memory, minus
the size of an integer
really minus the size of an pointer which 8 bytes on x64, when size of an integer always 4.
2. look at a reputable blog - The bonus window bytes at GWLP_USERDATA:
Note that this value, ..., belongs to the window class and not to the
code that creates the window... only the window class implementer may
read or write the values.
but exist also next two author remarks:
Interesting. I’m checking into that. But even if it does belong to the
creator of the window, enough window class implementations use it that
you still should stay away for safety’s sake.
and
I asked around and guidance is "unclear", though leaning slightly
towards "it belongs to the person who called CreateWindow". For
safety’s sake, then, you should just avoid it unless you can establish
clear ownership
again look for Managing Application State MSDN example - window class implementer used GWLP_USERDATA !
look for ATL atlhost.h - AtlAxWindowProc used GWLP_USERDATA
//case WM_CREATE:
::SetWindowLongPtr(hWnd, GWLP_USERDATA, (DWORD_PTR)pAxWindow);
again class implementer used GWLP_USERDATA
but under this agreement we can not use GWLP_USERDATA with CreateDialogParam, DialogBoxParam because here we not implementer (The DialogProc function is an application-defined callback function called from DefDlgProc - real class implementation code for dialogs - so only DefDlgProc can potential use GWLP_USERDATA cell)
so application that created the window or window class implementer is owner ?
if think - the variant application that created the window is more logical. window class implementer have two choice: can set cbWndExtra to sizeof(PVOID) and use index 0 or use GWLP_USERDATA index. when application that created the window - have no choice - only GWLP_USERDATA index or use another (less effective and more complex) way like SetProp, SetWindowSubclass, etc. so be logical if window class implementer use index 0 for bind self data to window and leave free GWLP_USERDATA for code that created the window. again how about CreateDialogParam, DialogBoxParam - most native way here for use data structure binds to dialog use GWLP_USERDATA index, but here we window creator, not dialog class implementer ! so can use GWLP_USERDATA or not ?
in all case need take to account that enough existing custom window class implementations use GWLP_USERDATA
my assumptions:
if we call CreateWindowEx for non windows core built-in
class - we must not use GWLP_USERDATA here
if we call CreateDialogParam, DialogBoxParam - i assume
that we can here use GWLP_USERDATA
if we call CreateWindowEx for windows built-in class (WC_*
named) we also can use GWLP_USERDATA
if we window class implementer - the best choice - set cbWndExtra
to sizeof(PVOID) and use index 0

Related

Calling FindWindowEx with program WIndowClass

I'm trying to use FindWindowEx to determine whether a certain program is running or not.
FindWindow(NULL, "Mozilla Firefox");
This works fine as long as I'm on firefox's start page. A workaround I found was:
FindWindow(NULL, "MozillaWindowClass");
But that left me wondering if that was specifically crafted for firefox, but it turns that it appeareantly works for other applications:
FindWindow(NULL, "OllyDbgWindowClass");
So my question is can I just use FindWindow with an argument like "programXWindowClass" for any program? Are there any exceptions to this?
Is "programXWindowClass" guaranteed to exist?
There is no requirement for a caller to RegisterClassEx to follow any particular pattern, that maps a window class name to any other information (like the application name). Any caller can pick any valid window class name they like.
Keep in mind two notable consequences of this:
A window class name need not be unique to any given application. All UWP applications use the window class "Windows.UI.Core.CoreWindow" by default, for example.
A window class name can change across different versions of an application, or even different invocations of an application.
Is "programXWindowClass" guaranteed to exist?
No. What you observed is merely a coincidence in naming.

MSDN terminology - Window procedure for the predefined control vs the control procedure

In a nutshell
Confused between the term "The window procedure for the predefined edit control window class" and "the edit control procedure".
In detail
I feel silly to ask this, but am I missing something from what is mentioned below?
from: MSDN
The window procedure for the predefined edit control window class
carries out default processing for all messages that the edit control
procedure does not process. When the edit control procedure returns
FALSE for any message, the predefined window procedure checks the
messages and carries out the following default actions.
*bold formatting by me
Let me specify my interpretation of above:
The window procedure for the predefined edit control window class: I believe this is the internal implementation of edit control's logic inside Windows (similar to any custom control we create).
The edit control procedure: Well this is something which I'm not able to interpret accurately. My wild guesses are:
Likely: It's our custom WndProc that we may subclass from edit control if we need to modify edit control default behaviour (say tab/carriage return processing etc.)
My self debate: In this case MSDN would have mentioned word "subclass" explicitly at least somewhere in article.
Unlikely: It's some abstracted/specialized internal Wndproc for windows that is class specific.
My self debate: If this was the case, there would be some mention of this somewhere.
What further adds to the confusion is the "When the edit control procedure returns FALSE for any message, the predefined window procedure checks the messages and carries out the following default actions" mentioned above. I believe the return value from a WndProc is always LRESULT and is message specific, and this TRUE/FALSE thing applies generally to DialogProcs. So what's the piece I am missing? Also even if I believe its a WndProc, return value does not decide the default processing, our explicitly calling DefWindowProc()/CallWindowProc() decides the default processing. So what is the return based processing above page talks about?
From the comments and research, it looks like this is to do with slightly inaccurate documentation on MSDN. Though I am sure folks at Microsoft can add some sense to it, maybe something related to internal implementation.

How to get parent form of nested VB6 UserControl

There is a similar question here, which unfortunately does not help me. When I make a call to UserControl.Parent, either a Form or another UserControl can be returned. If a Form is returned, I have what I want. But if a UserControl is returned, I have no way of iterating up the chain, since UserControl is the base class name, and I do not have access to the base class name outside of the control's implementation.
Technically, I could probably get around this by exposing the Parent property on every single UserControl in the application, but I would really like to avoid doing this (we have thousands of them).
My ultimate goal is to get a reference to the parent form which is hosting the control, so that the control can subscribe to the Form_Unload event. Here the control will remove and clean up a hosted .NET interopped control which is preventing the VB6 UserControl from raising its UserControl_Terminated event, thus leaking GDI objects and memory.
So far I have tried to make calls to GetParent(), GetWindow() and GetAncestor() functions in USER32.dll in the UserControl_Initialize and UserControl_Resize events, and then cross referencing with the hWnds on the forms in the Forms collection, but both of these events seem to be raised before the UserControl has been sited on its host form.
I did some fiddling around, and this should give you something to go on. I just created two UserControls, called Internal and External. Internal has a command button, External has a frame. I put an instance of Internal on External, inside the frame. Then I put an instance of External on a form, whose name I just left at Form1.
So, I have a control within a control on a form. The problem is to find a reference to Form from the context of the internal control.
First, I have a method called Test on the Form, so:
Public Sub Test
MsgBox "Test Succeeded"
End Sub
Now, in the internal control's command button's Click event handler:
Private Sub cmdTest_Click()
UserControl.ParentControls(0).Parent.Test
End Sub
Running the Form project and clicking the command button successfully calls the Form's Test method. (Yee ha.)
So, to distinguish between a nested control and a control directly on the form, you can do something along these lines:
Private Sub cmdTest_Click()
If TypeOf UserControl.Parent is Form Then
UserControl.Parent.Test
Else
UserControl.ParentControls(0).Parent.Test
End If
End Sub
I then tried nesting the external control in another control (External2) and putting an instance of External2 on the form. In the debug window, I did this:
? typename(usercontrol.ParentControls(0))
External
? typename(usercontrol.ParentControls(0).Parent)
External2
And that's as far as I got. Trying things like this:
? typename(usercontrol.ParentControls(0).Parent.ParentControls(0))
or anything similar, got an "Object doesn't support this property or method" error.
If you need to evaluate controls nested more than one deep (you haven't said for sure, but "iterate up the chain" suggests that you might), that might be beyond the capabilities of this technique. You can mess with the Controls and Name properties as well, and maybe figure something out. But it looks like the ParentControls property doesn't extend to parents of controls that are themselves controls, unless of course you go to the trouble of exposing them with a different property name. At least you can iterate one more link up the chain with this.
In general, it doesn't look like the Parent property or its derivatives contain actual references to the parent objects, but some sort of subset of their properties and methods. For example, I can get the hWnd property of the UserControl, but not of UserControl.Parent. Even specifically referencing the parent by name (the name of the actual control instance is External1, so ? External1.hWnd) fails to get the hWnd property, throwing an "Object Required" error. That would appear to complicate the possibility of using the API for a solution.
Anyway, I leave it to you to play around with. If you get further than I have, I would be interested to see your results.
I was able to find the parent form by traversing parent/child relationships using HWNDs and the win32 API. My code is roughly as follows:
Private Declare Function GetParent Lib "USER32" (ByVal Hwnd As Long) As Long
Private Declare Function GetClassName Lib "USER32" Alias "GetClassNameA" _
(ByVal Hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Public Function FindParentForm(Hwnd As Long) As Form
Dim ParentHwnd As Long
Dim CandidateForm As Form
Dim strTmp As String * 255
Dim lngLngth As Long
Dim strTitle As String
ParentHwnd = Hwnd
Do While (Not ParentHwnd = 0)
ParentHwnd = GetParent(ParentHwnd)
lngLngth = GetClassName(ParentHwnd, strTmp, 255)
strTitle = Left(strTmp, lngLngth)
'ThunderFormDC is the Debug version of a VB6 form, and ThunderRT6FormDC is the Release/Runtime version of a VB6 form
If strTitle = "ThunderFormDC" Or strTitle = "ThunderRT6FormDC" Then
Exit Do
End If
Loop
For Each CandidateForm In Forms
If CandidateForm.Hwnd = ParentHwnd Then
Set FindParentForm2 = CandidateForm
Exit Function
End If
Next
'Didn't find the parent form somehow
Set FindParentForm2 = Nothing
End Function
As I mentioned in the question, the problem with this solution is that during the UserControl_Initialize and UserControl_Resize events, the parent/child relationships have not been setup between HWNDs yet. If you try to traverse the parent/child relationships, you will find that the parent of the usercontrol is a class named "Static".
I was able to work around this issue by searching for the parent form in a manual Init() procedure for my user control. However, many forms do not call the Init() procedure unless the tab it is on is clicked on (in an attempt to get some sort of lazy loading implemented in VB6). I was able to work around this by refactoring the control to not dynamically create/add the .NET interopped control until the Init() procedure was called. By this time, the parent/child relationships seem to be set up.
An alternative solution to the lazy loading problem is to hook a WndProc procedure, and listen for the WM_CHILDACTIVATED message. However, this message only gets sent when the child control changes parents. It does not propogate to grandchildren. It should, however, be possible to hook another WndProc to the new parent control and listen for it's own WM_CHILDACTIVATED message and so on until a child control gets parented to a ThunderForm. However, since WndProc can only be implemented in a static module, I didn't feel like keeping track of parent/child relationships.
I'm rusty, but isn't the Container property what you're after?
Be aware, when interopping with dot net, that dot net has very different garbage collection. Just because the VB6 objects have been released doesn't mean that the dot net objects have been. They could still be lurking in memory and - in rare cases - could still be firing events on timers.
So make sure that your dot net control is cleaning itself up properly, and has a method which VB6 can fire in order to force this termination to occur.
See: https://msdn.microsoft.com/en-us/library/aa445702(v=vs.60).aspx
I solved my referencing problem using UserControl.Parent in ReadProperty.
I tried GetParent() with no success. Also tried UserControl.Parent in Initialize.
The problem is that during Initialize the object doesn't exist. It is being builted before link to form (Parent).
In ReadProperty (or Resize) it already exists and you will be able to use UserControl.Parent.
For example, I use UserControl.Parent.name to save some information in window register.
This is asociated with this topic so I post it here for use as necessary in special limited cases. It can't get too deep into the nesting, but was is a quick way to get information in my case and others may find it of use.
I have a a Control (cmdPageDown1) placed on a User Control, that is placed on a User Control (xMCGridNew1), which is placed on a Form (frmMC).
As others have pointed out, I can't get to the Form Name with any quick single line of code, BUT with these simple lines, I can get the names of the other 2 nested user controls and the lower level Control.
For Example:
'Debug.Print '[Roadblock Here] 'Top Level frm MC (Parent)
Debug.Print Screen.ActiveControl.Name 'SubLevel 1 xMCGridNew1 (Child)
Debug.Print UserControl.Name 'SubLevel 2 xpage (GrandChild)
Debug.Print ActiveControl.Name 'SubLevel 3 cmdPageDown1 (Great Grandchild)
This will yield in the immediate window corresponding to the three nest levels.
xMCGridNew1
xPage
cmdPageDown1
As mentioned by another poster (Orignal Poster) in this thread, regarding attempted use of the Container property:
The Container property has two issues. First, UserControl's do not have a >Container property. You must get it off of the UserControl.Extender >property. Second, the Container may be another UserControl. Since the >UserControl.Extender property is a base class property, it is not accessible >outside of that UserControl's specific implementation. I.e. UserControl1 >cannot access UserControl2.UserControl.Extender.Container. Thus the >Container property has the same problems as the Parent property - I would >need to modify every user control in our application (too many). – Taedrin >Jan 15 '16 at 15:08

Registering Window Class

I guess my question is relatively easy for those of you who spent time dealing with Win32 API.
So my question is:
After initializing a WNDCLASSEX instance we need to "register" it using the "RegisterClassEx" function, why? Why do we do that? What's the meaning of this registration and in what cases I need to register things?
The ATOM returned by RegisterClassEx uniquely identifies your "window class" which can then be referred to in other windows APIs. [MSDN]
Effectively it is a hash so as to reduce the amount of data processed each time a window is created or looked for. It does also mean that multiple windows with same features can be easily created and identified.
I was addressing the practical reasons above. Hans Passant's answer correctly explains this is the OO class concept provided for C. Further MSDN example.
The word Class in the function name is significant. When you write code in an object oriented language, like C++, Delphi, Java or C# etcetera, then you use the class keyword to create objects that have behavior. But the winapi was designed to be used from C, a language that doesn't have such functionality. The RegisterClassEx() function is an emulation of that, it lets you create a window that "derives" its behavior from a named class, behavior that you can override. With every window that you create using that class name behaving identically.
The WNDCLASSEX structure you pass gives a window its default behavior. The most significant members of this structure are:
lpszClassName. That's the equivalent of the C++ class name. You can later call CreateWindowEx() and pass that name to get a window that behaves a certain way. Windows itself calls RegisterClassEx() to register several of its built-in window classes that you then can readily re-use in your own code. "EDIT", "BUTTON" and "LISTBOX" are good examples of that.
lpfnWndProc. This is what gives a window class its specific default behavior. The address of its window procedure that implement message handlers for specific messages. You can further customize the default behavior, in other words "derive" your own class from the base class, by specifying another window procedure in the CreateWindowEx() call. Such a window procedure must always call DefWindowProc(), the equivalent of calling the base class method. Or in other words, a window has one virtual method.
hIcon, etcetera. These are the equivalent of properties of the base class, they set default values that affect the default message handlers. Helping you to keep your window procedure simple. It is for example rarely necessary to write a message handler for WM_ERASEBKGND, the hbrBackground member sets the default background for a window.
Windows requires you to call RegisterClassEx() even if you don't plan on re-using a window. Which is by far the most common usage of the function in your own code. You don't start to really take advantage of it until you write a library that implements controls, windows that other code can use. Like "EDIT".

Pattern for changing program options in a GUI

I'm adding a GUI to an existing command line app. The properties used by the app are held in class(es) and I'm creating a dialog that binds to those options objects. However, if I want to cancel out of that dialog I then have reset the values of my options objects, which is where I'm running into probs.
I could take an internal copy of the option objects and use that to re-populate the original object to allow the cancel/rollback but that seems cumbersome.
I can (somehow) implement an undo function on each class - is there a pattern for that?
I use the GUI controls standalone to hold values and only update the options objects when the dialog has been confirmed.
What's best practise?
You should consider creating a new class to be used just by the GUI.
GUIs have their own needs.
Make sure to take care of multi thread issues if you have more than one thread accessing the options object.
The design patterns that address undo functionality are called Command and Memento.
I think Memento would fit better on this case.
Take a look on this question on SO: Design Pattern for Undo Engine.
The following links are of interest (and many more):
http://www.coderanch.com/t/100676/patterns/Memento-Vs-Command-pattern
http://www.developer.com/design/article.php/3720566/Working-With-Design-Patterns-Memento.htm
http://www.colourcoding.net/blog/archive/2009/07/23/reversibility-patterns-memento-and-command.aspx

Resources