Is there a simple way to get a unique ID for the specific DLL instance some C/C++ code is currently running in? Maybe &DllMain? But that function is optional.
I'm writing a plugin dll that registers a window class name, but I need a different window class name for each plugin instance
No, you don't. DLLs don't have unique IDs, but they do have unique HINSTANCEs. Multiple DLLs can register the same class name, but still do different things. The classes are differentiated by the HINSTANCE that registers/creates them at runtime.
Refer to this for more info:
What is the HINSTANCE passed to CreateWindow and RegisterClass used for?
When it comes time to create a window, each module then passes its own HINSTANCE when creating the window, and the window manager uses the combination of the instance handle and the class name to look up the class.
CreateWindow("MyClass", ..., hinstA, ...); // creates class 6
CreateWindow("MyClass", ..., hinstB, ...); // creates class 7
CreateWindow("MyClass", ..., hinstC, ...); // fails
This is why it is okay if multiple DLLs all register a class called “MyClass”; the instance handle is used to tell them apart.
Related
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.
I am trying to use the function GetDlgItem(int id) and not the GetDlgItem(HWND par, int id). In other parts my code I use GetDlgItem as such
CWnd * pWnd;
pWnd = GetDlgItem(IDC_UPPER_BTN);
And it works fine. But in another class I am trying to do the exact same thing and it keeps demanding a HWND.
When I search GetDlgItem I see there is a MFC and a windows version. How can I specify which one I want to use?
You can specify the member function explicitly using:
this->GetDlgItem(...);
You can specify the global function explicitly using:
::GetDlgItem(...);
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".
I am trying to create a window with a certain class type ("VSDebugger CDataTipWnd"), however, when I run CreateWindowEx it fails, and GetLastError tells me that the class wasn't found. Here is the code for reference, though it shouldn't matter:
const Win32WindowStyles dwStyle = Win32WindowStyles.WS_POPUP;
IntPtr wnd = NativeMethods.CreateWindowEx(0L, "VSDebugger CDataTipWnd", "MyWindow",
dwStyle, 100, 100, 100, 100, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
I am running as a plug-in in the process and I know that a Window of this class is created before (I made sure of that using Winspector/Spy++), yet, when I try to create a window of this type myself, it doesn't work and I can't figure out why.
The documentation says that the "The class name can be any name registered with RegisterClass or RegisterClassEx, provided that the module that registers the class is also the module that creates the window. The class name can also be any of the predefined system class names. For a list of system class names, see the Remarks section." is it possible that the RegisterClass was indeed created in another module (dll/exe)? Does merely creating a class in another module make it inaccessible by name from another module?? If so, can I still find that class somehow and create a window with it?
Thanks!
Vitaly
You are passing IntPtr.Zero to the HINSTANCE argument.
The HINSTANCE of the module (EXE or DLL) which registered the class must be provided to CreateWindowEx.
If you think the main EXE registered the class then you can get its HINSTANCE via GetModuleHandle(IntPtr.Zero).
If another DLL registered the class then you'll need some way to know which one and get its HINSTANCE/HMODULE (the two are the same these days).
That's probably the case. Does the program provide an API to do this? You mention you're running as a plugin to it - I'd think that'd be the way to do it.
I am working on a set of what are essentially plugins, which are COM servers. Each plugin has a set of configuration data which is managed by another component, the primary key to the configuration data is the plug-in's ProgID. When the plugin needs to access a configuration item, it makes a call and passes in its ProgID and the name of the property required. This is a legacy design and I must maintain backward compatibility.
I now have a requirement to load multiple instances of each plugin, with each instance having a different set of configuration data. The solution I'm considering is to create multiple unique ProgIDs for each plugin, each ProgID would point to the single ClsId for the plugin. Thus, each instance of the plugin would be indentified by its ProgID, the ProgID is still used as the primary key for the configuration data and everything is 100% backward compatible.
So, the questions:
Is this an acceptable technique? (multiple ProgIDs all pointing to a single ClsID).
When my plugin loads, would it be able to tell which ProgID was used to create it?
Prog ids are typically used in two ways: to detect a class id corresponding to a prog id (CLSIDFromProgID() function) - this is used to later call CoCreateInstance() - and to detect a prog id for a given class id - this is usually used to display a human-friendly version of a class id.
Those mappings imply that there's a HKCR{ProgId}\CLSID key with a default value equal to the class id and a HKCR\CLSID{classid}\ProgID key with a default value equal to the ProgId, which means that the mapping is one-to-one. You will just not be able to have more than one prog id under one class id.
A COM component is loaded by calling CoCreateInstance() which is passed a class id - obtained by any means possible, using CLSIDFromProgID() included. There're no ways for a component to tell how the class id was obtained.