Будет ли Windows API «CreateWindowEx» работать в DLL, используемой 64-разрядной версией Python (3.6.8)?

У меня есть C++ DLL с открытой функцией API, использующей extern "C", и я использую эти функции в Python, используя функции-оболочки функций ctypes. По сути, я просто хочу сделать оболочку для доступа к API моей DLL.

Однако я заметил, что, хотя большинство моих функций работают правильно, функции, касающиеся зарегистрированного процесса обратного вызова и окна только для сообщений, использующие функции Windows API RegisterClassEx и CreateWindowEx, не работают.

Я использую 64-разрядную версию Python (3.6.8), поэтому мне было интересно, может ли быть несоответствие. Моя DLL 64-битная и работает в других средах. Есть ли причина, по которой Windows API не работает?

Результаты отладки:

Мой код достигает события WM_CREATE в процессе обратного вызова, но не достигает события WM_DEVICECHANGE. Опять же, этот код доступен в других средах, поэтому я пытаюсь выяснить, что отличается от Python.

Создание окна — это только одна десятая часть сражения. Остальные 90% запускают насос сообщений (см. GetMessage и др.). Что бы доставить WM_DEVICECHANGE и другие сообщения оконной процедуре. Для этого вам, вероятно, потребуется крутить нить.

Igor Tandetnik 17.07.2019 02:48
WM_CREATE отправляется самим CreateWindowEx() перед выходом, поэтому он не зависит от активного цикла сообщений, в отличие от большинства других сообщений.
Remy Lebeau 17.07.2019 05:46

Вы зарегистрировали это сообщение в своем приложении?

Drake Wu 17.07.2019 11:50

@RemyLebeau Я создал функции-оболочки на C# и могу вызывать функции из сред C++ (например, Qt), в которых всегда достигается WM_DEVICECHANGE. Я пытаюсь придумать причину, по которой Python будет заблокирован. Я проверил RegisterDeviceNotification, который возвращает true, поэтому я в тупике, почему не приходят уведомления. Моя DLL 64-битная, а Python 64-битная. Я также попробовал 32-битную DLL в 32-битной версии Python, которая тоже не сработала. Другие функции работают, поэтому просто система событий не получает уведомления.

karamazovbros 19.07.2019 19:23
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
4
644
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Windows только для сообщенийНЕ получают широковещательные сообщения:

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.

Вместо этого вы должны создать окно верхнего уровня и не вызывать showWindow.

Кроме того, не нужно вызывать CreateWindow/CreateWindowEx через DLL, попробуйте использовать WinAPI, импортировав модуль win32api, win32con, win32gui. Вот образец.

ОБНОВИТЬ:

Пример C++, который не может получить WM_DEVICECHANGE с окном только для сообщений.

#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);
        }
    }
}

Обновлено:

Накачка сообщений необходима после создания окна.

Он работает и в других средах, в основе которых лежат C# и C++. Я получаю уведомления о событиях без каких-либо проблем, поэтому я не думаю, что ваш ответ применим. Это единственное, с чем я столкнулся, когда пробовал это на Python. Импорт других модулей противоречит цели создания оболочки для DLL.

karamazovbros 17.07.2019 05:18

Нет, это не так. Хотя я не знаю, как работает ваша среда (поскольку я не вижу кода), но я могу поделиться протестированным мной образцом C++, который не может получить сообщение WM_DEVICECHANGE с окном только для сообщений.

Drake Wu 17.07.2019 08:34

Также см. это, stackoverflow.com/questions/10168467/…

Drake Wu 17.07.2019 08:44

@DavidHeffernan Вы имеете в виду, что окна только для сообщений могут получать WM_DEVICECHANGE или транслировать сообщения в python или в DLL?

Drake Wu 17.07.2019 11:32

Вы можете зарегистрироваться, чтобы получать эти сообщения. Не спешите делать вывод, что спрашивающий ожидает приема трансляций. Также прочитайте вопрос, функциональность, связанная с зарегистрированным процессом обратного вызова.

David Heffernan 17.07.2019 11:47

Давайте продолжить обсуждение в чате.

Drake Wu 17.07.2019 12:02

Другие вопросы по теме