I'm trying to call the Win32 version of SetWindowPos from within an ATL class (I need to specify a different first hWnd, which ATL normally handles), but I can't 'break out' of the ATL class and get the following error:
error C2661: 'ATL::CWindow::SetWindowPos' : no overloaded function
takes 7 arguments
How do I tell it I don't want to use the one in my base class?!
Dumbass answer... suppose someone else might have the same problem.
Prefix :: to access the global namespace. (Courtesy of CodeGuru).
Related
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.
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.
In my previous question, I asked why I kept getting the error message bad DLL calling convention when trying to call functions from a DLL. The general consensus was that I needed to change the calling convention to cdecl. Makes sense.
Unfortunately, I cannot place it right there on the function declaration importation. I had to either "create a wrapper DLL" or "create a type library for the DLL."
I am very unfamiliar with VB as my main focus at work is C# and this is the first time working in the language for a very long time. I'm not sure exactly how to accomplish this task.
I'm also confused as to how a wrapper DLL helps things. Supposedly I can't decorate a function import with cdecl in my code but if I move that exact function import to a new VB6 DLL and then reference that DLL it suddenly works?
I actually think this question was better on the topic.
To sum up, you can "place it right there on the function declaration importation", but the VB6 IDE doesn't know how to debug such a thing. But the compiler deals with it just fine. Once you compile it into a dll then your main project can access the functionality that was compiled.
Perhaps you are asking how to move these into a dll? If that is the case, you need to create a new Project of type "ActiveX Dll". Name it something like PwrUSB. Next, add a class (or rename the default/empty one if it is provided) to something like PwrUSBApi. Next, in the properties window, set the class to GlobalMultiUse. In a module called MDeclares, drop in all of your declarations:
'from your other post...
Public Declare Function InitPowerDevice CDecl Lib "PwrDeviceDll.dll" (ByRef firmware() As Byte) As Long
Back in your PwrUSBApi class:
'forward your calls to the dll
Public Function InitPowerDevice (ByRef firmware() As Byte) As Long
InitPowerDevice = MDeclares.InitPowerDevice(firmware)
End Function
You could create a more fully fledged object model from the API, but I'd start with this simple wrapper until you sort out all of the APIs.
Oh yeah, back in your main project you'd add a reference your new wrapper PwrUSB.dll in the Project menu. Then in the code you would use it something like this:
Dim numOfDevices as Long
Dim firmware() As Byte
Redim firmware(0 to 31)
numOfDevices = PwrUSB.InitPowerDevice(firmware)
Good luck.
A wrapper DLL in VB6 would still need to use the CDecl decorator or else a typelib created to deal with the DLL's function signatures.
The only advantage in creating a VB6 wrapper for this is to make it easier to debug the calling program from within the VB6 IDE, where CDecl has no effect. The wrapper would be small, and created once as a native code DLL, making CDecl effective there.
See your other thread(s) for additional answers. I suspect your real problem is that you were not passing the right kind of argument.
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.