Hi to all,
I need to detect the presence of the CS_GLOBALCLASS flag in a control (of an external application) and noticed that both GetClassLong() and GetClassInfo() failed to return the right style even on a simple static control created from an empty project:
HWND ctrl = CreateWindow(TEXT("STATIC"), TEXT("Label 1"), WS_CHILD | WS_VISIBLE | SS_LEFT, 0, 0, 50, 25, hWnd, NULL, hInstance, NULL); LONG style = GetClassLong(ctrl, -26);
For the above control Spy++ recognizes the right style (0x00000088 = CS_DBLCLKS | CS_PARENTDC), but when I call GCL (or else GCI), the returned value is wrong:
0x00004088 (= CS_DBLCLKS | CS_PARENTDC | CS_GLOBALCLASS).
Anyone know a bit more about this strange behaviour? I've looked the Windows Classes documentation and found no mention on the fact that GetClassLong() and GetClassInfo() may return wrong styles on certain controls.
- Edited by clarkxx Tuesday, January 15, 2013 4:26 AM
Spy reads the window style and not the class style.
So you need to use the GetWindowLong function.
GetWindowLong retrieves the attributes of the window created using CreateWindow and GetClassLong retrieves the attributes of the WNDCLASS structure used by RegisterClass.
- Proposed as answer by Bordon Tuesday, January 15, 2013 5:46 AM
Hi and thanks for your help.
I'm not sure if Spy++ may change between different versions of VS, but in the one bundled with VS2010, the class style is located on the fourth tab of the property inspector. The second field, "Class Styles", show the exadecimal style along with a combobox filled with the name of every single style.
I've taken a look at GetWindowLong, but the styles retrieved from this function are only the base and extended window styles. There is no ability to retrieve the class styles.
If I'm not wrong, GetClassLong() return the right style only when RegisterClass is used.
So, If I can find a way to detect when RegisterClass is used, I can trust the result returned from GetClassLong(). The two main problems that I can think right now is how to check for IsRegisterClassCalled and, if the result of the condition is false, how I can check for the presence of the CS_GLOBALCLASS if GetClassLong() returns wrong results?
What I don't understand is that Spy++ recognizes the right class styles independently from the fact that RegisterClass is used or not.
Here is something you could try -
Call GetClassName using the window handle to get the name of the class used to create the window.
Then use GetClassInfoEx to get the WNDCLASSEX structure associated with the window.
This is the structure that RegisterClassEx uses to register the class.
You could then examine the members of this structure.
Thanks for your suggestion, but unfortunately I'm afraid that will never work.
It appears to be that GetClassInfoEx() does not support cross process calls. The significate of the hInstance parameter is unknown because even If I provide the hInstance of the target process, the function still search between the list of classes registered by the calling process.
The only way to get this to work is to inject GetClassInfoEx() function into the target process and run the function from there. This is what already does Spy++.
GetClassLong() appears to support cross process calls. When the external process create the window using the class registered with RegisterClass, I can get the correct style. The main problem is that when the external process does not call RegisterClass and only creates a window using a system class (as showed in the sample code posted at the beginning of this thread), GetClassLong() does not fail and the returned style also includes an inexistent CS_GLOBALCLASS. Since my application depends exclusively from the presence of this bit, the execution will break if GetClassLong() says that it is present while it isn't.
As a possible workaround I've tried (without success) to register the same class again. I thought that If RegisterClass() fails with error "class already exist", I can stay sure that the style returned from GetClassLong() is the right one.
Unfortunately every call to RegisterClass() always succeds and the reason is the same I mentioned before: the function must be executed on the same address space of the target process.
At this point I'm out of resources and I continue to not understand why GetClassLong() likes to add a bit that does not exist.
I would have never thought that was so hard (if not impossible) to get the window-class style bits expecially because GetClassLong() it was designed to return this kind of data by simply passing GCL_STYLE as parameter.
- Edited by clarkxx Thursday, January 17, 2013 3:04 AM