CreateWindowEx fails with ERROR_CANNOT_FIND_WND_CLASS - windows

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.

Related

get unique ID for Win32 DLL instance?

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.

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.

Creating systray icon with vbscript?

I can only use vbscript on this computer, I would like to display an icon in the systray.
I found a similar question and an answer using VBA.
Display new mail icon in Windows taskbar using VBScript
There is also this code from Microsoft which explains how to do it from VBA
How to use the System Tray directly from Visual Basic
These solution work with the following API call
Public Declare Function Shell_NotifyIcon Lib "shell32" _
Alias "Shell_NotifyIconA" _
(ByVal dwMessage As Long, pnid As NOTIFYICONDATA) As Boolean
The problem is how to create the user-defined type in vbscript.
Public Type NOTIFYICONDATA
cbSize As Long
hwnd As Long
uId As Long
uFlags As Long
uCallBackMessage As Long
hIcon As Long
szTip As String * 64
End Type
VBScript only has a "variant" for all variable, there isn't a TYPE statement to create the kind of thing Shell_NotifyIcon needs.
I have read somewhere the possibility of using a class statement.
Perhaps something like this ?
Class NOTIFYICONDATA
cbSize
hwnd
uId
uFlags
uCallBackMessage
hIcon
szTip(64)
End Class
However I think my syntax is wrong or that the class object doesn't work that way. Or maybe, since each component of that class is a variant instead of the type that Shell_NotifyIcon expect, it won't work ?
I don't mind using a ugly has to force vbscript engine into making the proper memory object to use the API call, if there is any way ?
(In a later episode, if I manage to create a systray icon, I would like to get click events from the icon and display a context menu (vbscript lacks a form object to create user interfaces, except for the extremely limited forms from the HTA objects which I rather not use))
As pointed out by #Lankymart, VBScript can't use Windows APIs directly. You could write a COM wrapper that exposes particular interfaces to VBScript, but then you could just as well implement your whole application in VB6 or VB.net.

GetDlgItem, works in one class and not in another

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(...);

Break out of ATL class into Win32 functions

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).

Resources