0

I have a C++ DLL with exposed API function using extern "C" and I utilize these functions in Python using function ctypes wrapper functions. Essentially, I just want to make a wrapper to access the API of my DLL.

However, I noticed that while most of my functions work correctly, the functionality regarding a registered callback process and a message-only window utilizing the Windows API functions RegisterClassEx and CreateWindowEx don't work.

I'm using Python (3.6.8) 64-bit, so I was wondering if there might be a mismatch. My DLL is 64-bit and it works in other environments. Is there any reason just the Windows API doesn't work?

Debugging Results:

My code reaches the WM_CREATE event within the callback process, but doesn't reach WM_DEVICECHANGE event. Again, this code is reached in other environments, so I'm trying to figure out what's different using Python.

karamazovbros
  • 950
  • 1
  • 11
  • 40
  • 2
    Creating a window is only one-tenth of a battle. The other 90% is running the message pump (see `GetMessage` et al). What's what would deliver `WM_DEVICECHANGE` and other messages to the window procedure. You'd probably need to spin a thread for that. – Igor Tandetnik Jul 17 '19 at 00:48
  • `WM_CREATE` is sent by `CreateWindowEx()` itself before it exits, so it does not rely on an active message loop, unlike most other messages – Remy Lebeau Jul 17 '19 at 03:46
  • Did you register these message in you application? – Drake Wu Jul 17 '19 at 09:50
  • @RemyLebeau I've created wrapper functions in C# and can call the functions from C++ environments (like Qt), in which WM_DEVICECHANGE is always reached. I'm trying to think of the reason why Python would get blocked. I checked RegisterDeviceNotification, which returns true, so I'm stumped as to why no notifications are coming in. My DLL is 64 bit and Python is 64 bit. I also tried a 32 bit DLL in 32 bit version of Python, which didn't work either. Other functions works, so just the event system isn't receiving notifications. – karamazovbros Jul 19 '19 at 17:23

1 Answers1

1

Message-Only Windows DOES NOT receive broadcast messages:

A message-only window enables you to send and receive messages. It is not visible, has no z-order, cannot be enumerated, and does not receive broadcast messages. The window simply dispatches messages.

Instead, you should create a top-level window and do not call showWindow.

In addition, you don't need to call CreateWindow/CreateWindowEx through DLL, try to use WinAPI by importing the module win32api, win32con, win32gui. Here is an sample.

UPDATE:

C++ sample that cannot receive WM_DEVICECHANGE with Message-only window.

#include <windows.h>
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_CREATE:
        MessageBox(NULL, "WM_CREATE", "Message", 0);
        break;
    case WM_DEVICECHANGE:
        MessageBox(NULL, "WM_DEVICECHANGE", "Message", 0);
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
int main()
{
    static const char* class_name = "NAME_CLASS";
    WNDCLASSEX wx = {};
    HWND hwnd;
    HINSTANCE hInstance = GetModuleHandleA(NULL);
    wx.cbSize = sizeof(WNDCLASSEX);
    wx.lpfnWndProc = WndProc;        // function which will handle messages
    wx.hInstance = hInstance;
    wx.lpszClassName = class_name;
    if (RegisterClassEx(&wx)) {
        hwnd = CreateWindowEx(0, class_name, "Title", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
    //  hwnd = CreateWindowEx(0, class_name, "Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    //  Create a normal top-level window which can receive the broadcast messages. 
    }
    HACCEL hAccelTable = LoadAccelerators(hInstance, class_name);
    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
}

EDIT:

Pump messages is needed after create window.

Drake Wu
  • 6,927
  • 1
  • 7
  • 30
  • It works in other environments that utilize C# and C++ as their foundation. I get event notifications without any problems, so I don’t think your answer applies. This only something I’ve faced when trying it out in Python. Importing other modules defeats the purpose of creating a wrapper for the DLL. – karamazovbros Jul 17 '19 at 03:18
  • No, it doesn't. Although I don't know how your environment works(Since I haven't see the code), but I can share a C++ sample which I've tested that could not get the `WM_DEVICECHANGE` message with Message-only Window. – Drake Wu Jul 17 '19 at 06:34
  • Also see this, https://stackoverflow.com/questions/10168467/catching-the-wm-devicechange?answertab=active#tab-top – Drake Wu Jul 17 '19 at 06:44
  • @DavidHeffernan Do you mean message-only windows can get `WM_DEVICECHANGE` or broadcast message in python or in a DLL? – Drake Wu Jul 17 '19 at 09:32
  • 1
    You can register to receive these messages. Don't leap to conclude that asker is expecting to receive broadcasts. Also, read the question, *the functionality regarding a registered callback process*. – David Heffernan Jul 17 '19 at 09:47
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/196560/discussion-between-drake-wu-msft-and-david-heffernan). – Drake Wu Jul 17 '19 at 10:02