Windows Fenster erzeugen

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Frühlingsrolle
User
Beiträge: 4
Registriert: Donnerstag 30. April 2020, 06:59

Hallo Forum,

ich benutze Python 3.6 für Windows (64-bit) und versuche allein mit dem Modul "ctypes" (ohne win32api etc.) ein Windows-Fenster zu erzeugen.
Das Projekt kompiliert zwar, ein Fenster wird nicht erzeugt und erscheint ebenso nicht im Taskmanager.
Was mache ich falsch?

Es ist nur ein Übungsprojekt.

Code: Alles auswählen

from ctypes import *

# Types
ATOM = c_ushort
BOOL = c_bool
DWORD = c_ulong
HANDLE = c_void_p
HBRUSH = HANDLE
HICON = HANDLE
HCURSOR = HICON
HINSTANCE = HANDLE
HMENU = HANDLE
HWND = HANDLE
INT = c_int
LONG = c_long
LONG_PTR = c_long
LPARAM = LONG_PTR
LPCWSTR = c_wchar_p
LPVOID = c_void_p
LRESULT = LONG_PTR
UINT = c_uint
UINT_PTR = c_uint
WPARAM = UINT_PTR
# Callbacks
WNDPROC = WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM)

# Window styles
WS_BORDER = 0x00800000
WS_CAPTION = 0x00C00000
WS_VISIBLE = 0x10000000


class POINT(Structure):
    _fields_ = [('x', LONG),
                ('y', LONG)]


class MSG(Structure):
    _fields_ = [('hwnd', HWND),
                ('message', UINT),
                ('wParam', WPARAM),
                ('lParam', LPARAM),
                ('time', DWORD),
                ('pt', POINT)]


class WNDCLASSW(Structure):
    _fields_ = [('style', UINT),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', INT),
                ('cbWndExtra', INT),
                ('hInstance', HINSTANCE),
                ('hIcon', HICON),
                ('hCursor', HCURSOR),
                ('hbrBackground', HBRUSH),
                ('lpszMenuName', LPCWSTR),
                ('lpszClassName', LPCWSTR)]


def CreateWindowW(lpClassName, lpWindowName: LPCWSTR, dwStyle: DWORD, x, y, nWidth, nHeight: INT,
                  hWndParent: HWND, hMenu: HMENU, hInstance: HINSTANCE, lpParam: LPVOID) -> HWND:
    return windll.user32.CreateWindowExW(0, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent,
                                         hMenu, hInstance, lpParam)


def DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT:
    return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)


def DispatchMessageW(lpMsg: POINTER(MSG)) -> LRESULT:
    return windll.user32.DispatchMessageW(lpMsg)


def GetMessageW(lpMsg: POINTER(MSG), hWnd: HWND, wMsgFilterMin, wMsgFilterMax: UINT) -> BOOL:
    return windll.user32.GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax)


def RegisterClassW(lpWndClass: POINTER(WNDCLASSW)) -> ATOM:
    return windll.user32.RegisterClassA(lpWndClass)


def TranslateMessage(lpMsg: POINTER(MSG)) -> BOOL:
    return windll.user32.TranslateMessage(lpMsg)


"""
def PostQuitMessage(nExitCode: INT):
    windll.user32.PostQuitMessage(nExitCode)
"""


def WindowProc(hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT:
    return DefWindowProcW(hwnd, uMsg, wParam, lParam)


def main():
    wc = WNDCLASSW()
    wc.lpfnWndProc = WNDPROC(WindowProc)
    wc.hInstance = 0
    wc.lpszClassName = "myPython"
    RegisterClassW(pointer(wc))
    CreateWindowW("myPython", "Python1", WS_BORDER | WS_CAPTION | WS_VISIBLE, 40, 40, 400, 400, None, None, None, None)
    msg = MSG()
    while GetMessageW(pointer(msg), None, None, None):
        TranslateMessage(pointer(msg))
        DispatchMessageW(pointer(msg))


if __name__ == "__main__":
    main()
__deets__
User
Beiträge: 14480
Registriert: Mittwoch 14. Oktober 2015, 14:29

Vor allem pruefst du keine Rueckgabewerte, welche dir Einblick verschaffen koennten.
Frühlingsrolle
User
Beiträge: 4
Registriert: Donnerstag 30. April 2020, 06:59

Mit Abfragen und diversen Casts funktioniert es nun:

Code: Alles auswählen

# from ctypes import windll  # windll = stdcall convention
from ctypes import *

# Types
ATOM = c_ushort
BOOL = c_bool
DWORD = c_ulong
HANDLE = c_void_p
HBRUSH = HANDLE
HICON = HANDLE
HCURSOR = HICON
HINSTANCE = HANDLE
HMENU = HANDLE
HMODULE = HINSTANCE
HWND = HANDLE
INT = c_int
LONG = c_long
LONG_PTR = c_long
LPARAM = LONG_PTR
LPCWSTR = c_wchar_p
LPVOID = c_void_p
LRESULT = LONG_PTR
UINT = c_uint
UINT_PTR = c_uint
WPARAM = UINT_PTR
# Callbacks
WNDPROC = WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM)

# Window styles
WS_BORDER = 0x00800000
WS_CAPTION = 0x00C00000
WS_SYSMENU = 0x00080000
WS_VISIBLE = 0x10000000

# Window messages
WM_DESTROY = 2


class POINT(Structure):
    _fields_ = [('x', LONG),
                ('y', LONG)]


class MSG(Structure):
    _fields_ = [('hwnd', HWND),
                ('message', UINT),
                ('wParam', WPARAM),
                ('lParam', LPARAM),
                ('time', DWORD),
                ('pt', POINT)]


class WNDCLASSW(Structure):
    _fields_ = [('style', UINT),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', INT),
                ('cbWndExtra', INT),
                ('hInstance', HINSTANCE),
                ('hIcon', HICON),
                ('hCursor', HCURSOR),
                ('hbrBackground', HBRUSH),
                ('lpszMenuName', LPCWSTR),
                ('lpszClassName', LPCWSTR)]


def CreateWindowW(lpClassName: LPCWSTR, lpWindowName: LPCWSTR, dwStyle: DWORD, x: INT, y: INT, nWidth: INT,
                  nHeight: INT, hWndParent: HWND, hMenu: HMENU, hInstance: HINSTANCE, lpParam: LPVOID) -> HWND:
    return windll.user32.CreateWindowExW(0, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent,
                                         hMenu, hInstance, lpParam)


def DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT:
    return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)


def DispatchMessageW(lpMsg: POINTER(MSG)) -> LRESULT:
    return windll.user32.DispatchMessageW(lpMsg)


def GetMessageW(lpMsg: POINTER(MSG), hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> BOOL:
    return windll.user32.GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax)


def GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE:
    return windll.kernel32.GetModuleHandleW(lpModuleName)


def RegisterClassW(lpWndClass: POINTER(WNDCLASSW)) -> ATOM:
    return windll.user32.RegisterClassW(lpWndClass)


def TranslateMessage(lpMsg: POINTER(MSG)) -> BOOL:
    return windll.user32.TranslateMessage(lpMsg)


def MessageBoxW(hwnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT) -> INT:
    return windll.user32.MessageBoxW(hwnd, lpText, lpCaption, uType)


def PostQuitMessage(nExitCode: INT):
    windll.user32.PostQuitMessage(nExitCode)


def WindowProc(hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT:
    if uMsg == WM_DESTROY:
        PostQuitMessage(0)
        return 0

    return DefWindowProcW(hwnd, uMsg, wParam, lParam)


def main():
    # hInstance = GetModuleHandleW(None)
    className = "myPython"

    wc = WNDCLASSW()
    wc.lpfnWndProc = WNDPROC(WindowProc)
    wc.hInstance = 0
    wc.lpszClassName = LPCWSTR(className)

    result = RegisterClassW(pointer(wc))
    # print(result)
    if result != 0:
        result = CreateWindowW(LPCWSTR(className), LPCWSTR("パイソン"), DWORD(WS_SYSMENU | WS_CAPTION | WS_BORDER | WS_VISIBLE),
                               50, 50, 300, 300, None, None, None, None)
        # print(result)
        if result is not None:
            msg = MSG()
            while GetMessageW(pointer(msg), None, 0, 0):
                TranslateMessage(pointer(msg))
                DispatchMessageW(pointer(msg))


if __name__ == "__main__":
    main()
Frühlingsrolle
User
Beiträge: 4
Registriert: Donnerstag 30. April 2020, 06:59

Mir stürzt die Anwendung beim Ausführen des Skripts mit Python 3.6.1 (64-bit) IDLE ständig ab, was hingegen mit Python 3.6.2 (32-bit) IDLE problemlos funktioniert.
Ausgeführt wird es unter Windows 7 64-bit.
Beim Anwenden von PyCharm Community Edition 2020.1 wird mir dabei folgender Fehler ausgegeben:
"Process finished with exit code -1073741819 (0xC0000005)"
Vorausgesetzt, ich verwende den 64-bit Interpreter:

Code: Alles auswählen

from ctypes import *

# Types
ATOM = c_ushort
BOOL = c_bool
BYTE = c_byte
DWORD = c_ulong
HANDLE = c_void_p
HBRUSH = HANDLE
HDC = HANDLE
HICON = HANDLE
HCURSOR = HICON
HINSTANCE = HANDLE
HMENU = HANDLE
HMODULE = HINSTANCE
HWND = HANDLE
INT = c_int
LONG = c_long
LONG_PTR = c_long
LPARAM = LONG_PTR
LPCWSTR = c_wchar_p
LPVOID = c_void_p
LRESULT = LONG_PTR
UINT = c_uint
UINT_PTR = c_uint
WPARAM = UINT_PTR
# Callbacks
WNDPROC = WINFUNCTYPE(LRESULT, HWND, UINT, WPARAM, LPARAM)

# LoadCursor() - lpIconName
# hInstance must be "None"
IDC_APPSTARTING = 32650  # Standard arrow and small hourglass
IDC_ARROW = 32512  # Standard arrow
IDC_CROSS = 32515  # Crosshair
IDC_HAND = 32649  # Hand
IDC_HELP = 32651  # Arrow and question mark
IDC_IBEAM = 32513  # I-beam
IDC_ICON = 32641  # Obsolete for applications marked version 4.0 or later.
IDC_NO = 32648  # Slashed circle
IDC_SIZE = 32640  # Obsolete for applications marked version 4.0 or later. Use IDC_SIZEALL.
IDC_SIZEALL = 32646  # Four-pointed arrow pointing north, south, east, and west
IDC_SIZENESW = 32643  # Double-pointed arrow pointing northeast and southwest
IDC_SIZENS = 32645  # Double-pointed arrow pointing north and south
IDC_SIZENWSE = 32642  # Double-pointed arrow pointing northwest and southeast
IDC_SIZEWE = 32644  # Double-pointed arrow pointing west and east
IDC_UPARROW = 32516  # Vertical arrow
IDC_WAIT = 32514  # Hourglass

# LoadIcon() - lpIconName
# hInstance must be "None"
IDI_APPLICATION = 32512  # Default application icon.
IDI_ASTERISK = 32516  # Asterisk icon. Same as IDI_INFORMATION.
IDI_ERROR = 32513  # Hand-shaped icon.
IDI_EXCLAMATION = 32515  # Exclamation point icon. Same as IDI_WARNING.
IDI_HAND = 32513  # Hand-shaped icon. Same as IDI_ERROR.
IDI_INFORMATION = 32516  # Asterisk icon.
IDI_QUESTION = 32514  # Question mark icon.
IDI_SHIELD = 32518  # Security Shield icon.
IDI_WARNING = 32515  # Exclamation point icon.
IDI_WINLOGO = 32517  # Default application icon. Windows 2000:  Windows logo icon.

# LoadImage() - uType
IMAGE_BITMAP = 0
IMAGE_ICON = 1
IMAGE_CURSOR = 2

# LoadImage() - fuLoad
LR_DEFAULTSIZE = 0x00000040
LR_LOADFROMFILE = 0x00000010
LR_SHARED = 0x00008000

# SetBkMode() - modes
TRANSPARENT = 1
OPAQUE = 2

# Color types
COLOR_WINDOW = 5

# Window class styles
CS_VREDRAW = 0x0001
CS_HREDRAW = 0x0002
CS_DBLCLKS = 0x0008

# Window styles
WS_BORDER = 0x00800000
WS_CAPTION = 0x00C00000
WS_CHILD = 0x40000000
WS_DISABLED = 0x08000000
WS_DLGFRAME = 0x00400000
WS_MAXIMIZE = 0x01000000
WS_MAXIMIZEBOX = 0x00010000
WS_MINIMIZE = 0x20000000
WS_MAXIMIZEBOX = 0x00020000
WS_OVERLAPPEDWINDOW = 0x00CF0000
WS_POPUP = 0x80000000
WS_POPUPWINDOW = 0x7F780000
WS_SYSMENU = 0x00080000
WS_THICKFRAME = 0x00040000
WS_VISIBLE = 0x10000000

# Window messages
WM_DESTROY = 2
WM_PAINT = 0xF


class tagRECT(Structure):
    _fields_ = [('left', LONG),
                ('top', LONG),
                ('right', LONG),
                ('bottom', LONG)]


RECT = tagRECT
LPRECT = PRECT = POINTER(tagRECT)


class tagPAINTSTRUCT(Structure):
    _fields_ = [('hdc', HDC),
                ('fErase', BOOL),
                ('rcPaint', RECT),
                ('fRestore', BOOL),
                ('fIncUpdate', BOOL),
                ('rgbReserved', BYTE)]


PAINTSTRUCT = tagPAINTSTRUCT
LPPAINTSTRUCT = PPAINTSTRUCT = POINTER(tagPAINTSTRUCT)


class tagPOINT(Structure):
    _fields_ = [('x', LONG),
                ('y', LONG)]


POINT = tagPOINT
LPPOINT = PPOINT = POINTER(tagPOINT)


class tagMSG(Structure):
    _fields_ = [('hwnd', HWND),
                ('message', UINT),
                ('wParam', WPARAM),
                ('lParam', LPARAM),
                ('time', DWORD),
                ('pt', POINT)]


MSG = tagMSG
LPMSG = PMSG = POINTER(tagMSG)


class tagWNDCLASSW(Structure):
    _fields_ = [('style', UINT),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', INT),
                ('cbWndExtra', INT),
                ('hInstance', HINSTANCE),
                ('hIcon', HICON),
                ('hCursor', HCURSOR),
                ('hbrBackground', HBRUSH),
                ('lpszMenuName', LPCWSTR),
                ('lpszClassName', LPCWSTR)]


WNDCLASSW = tagWNDCLASSW
LPWNDCLASSW = PWNDCLASSW = POINTER(tagWNDCLASSW)


def BeginPaint(hWnd: HWND, lpPaint: LPPAINTSTRUCT) -> HDC:
    return windll.user32.BeginPaint(hWnd, lpPaint)


def CreateWindowW(lpClassName: LPCWSTR, lpWindowName: LPCWSTR, dwStyle: DWORD, x: INT, y: INT, nWidth: INT,
                  nHeight: INT, hWndParent: HWND, hMenu: HMENU, hInstance: HINSTANCE, lpParam: LPVOID) -> HWND:
    return windll.user32.CreateWindowExW(0, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent,
                                         hMenu, hInstance, lpParam)


def DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT:
    return windll.user32.DefWindowProcW(hWnd, Msg, wParam, lParam)


def DispatchMessageW(lpMsg: POINTER(MSG)) -> LRESULT:
    return windll.user32.DispatchMessageW(lpMsg)


def EndPaint(hWnd: HWND, lpPaint: LPPAINTSTRUCT) -> BOOL:
    return windll.user32.EndPaint(hWnd, lpPaint)


def GetMessageW(lpMsg: LPMSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> BOOL:
    return windll.user32.GetMessageW(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax)


def GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE:
    return windll.kernel32.GetModuleHandleW(lpModuleName)


def LoadCursorW(hInstance: HINSTANCE, lpCursorName: LPCWSTR) -> HCURSOR:
    return windll.user32.LoadCursorW(hInstance, lpCursorName)


def LoadIconW(hInstance: HINSTANCE, lpIconName: LPCWSTR) -> HICON:
    return windll.user32.LoadIconW(hInstance, lpIconName)


def LoadImageW(hInst: HINSTANCE, name: LPCWSTR, uType: UINT, cx: INT, cy: INT, fuLoad: UINT) -> HANDLE:
    return windll.user32.LoadImageW(hInst, name, uType, cx, cy, fuLoad)


def PostQuitMessage(nExitCode: INT):
    windll.user32.PostQuitMessage(nExitCode)


def RegisterClassW(lpWndClass: POINTER(WNDCLASSW)) -> ATOM:
    return windll.user32.RegisterClassW(lpWndClass)


def SetBkMode(hdc: HDC, mode: INT) -> INT:
    return windll.gdi32.SetBkMode(hdc, mode)


def TextOutW(hdc: HDC, x: INT, y: INT, lpString: LPCWSTR, c: INT) -> BOOL:
    return windll.gdi32.TextOutW(hdc, x, y, lpString, c)


def TranslateMessage(lpMsg: POINTER(MSG)) -> BOOL:
    return windll.user32.TranslateMessage(lpMsg)


def MessageBoxW(hwnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT) -> INT:
    return windll.user32.MessageBoxW(hwnd, lpText, lpCaption, uType)


def WindowProc(hwnd: HWND, uMsg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT:
    if uMsg == WM_PAINT:
        ps = PAINTSTRUCT()
        hdc = BeginPaint(hwnd, pointer(ps))
        text = "こんにちは世界"
        SetBkMode(hdc, TRANSPARENT)
        TextOutW(hdc, 10, 10, LPCWSTR(text), len(text)) 
        EndPaint(hwnd, pointer(ps))
        return 0
    if uMsg == WM_DESTROY:
        PostQuitMessage(0)
        return 0

    return DefWindowProcW(hwnd, uMsg, wParam, lParam)


def main():
    className = "myPython"
    iconPath = r"C:\Users\---\Pictures\Meine Dragonball Icons\Ico\Dragonball32x32.ico"

    wc = WNDCLASSW()
    wc.style = CS_DBLCLKS
    wc.lpfnWndProc = WNDPROC(WindowProc)
    wc.hbrBackground = HBRUSH(COLOR_WINDOW)
    wc.cbClsExtra = 0
    wc.cbWndExtra = 0
    wc.hInstance = None
    wc.hIcon = LoadImageW(wc.hInstance, LPCWSTR(iconPath), IMAGE_ICON, 0, 0,
                          LR_LOADFROMFILE | LR_DEFAULTSIZE | LR_SHARED)
    # wc.hIcon = LoadIconW(wc.hInstance, LPCWSTR(IDI_WARNING))
    wc.hCursor = LoadCursorW(wc.hInstance, LPCWSTR(IDC_HAND))
    wc.lpszMenuName = None
    wc.lpszClassName = LPCWSTR(className)

    result = RegisterClassW(pointer(wc))
    print(result)
    if result != 0:
        result = CreateWindowW(LPCWSTR(className), LPCWSTR("パイソン"), DWORD(WS_OVERLAPPEDWINDOW | WS_VISIBLE),
                               50, 50, 300, 300, None, None, wc.hInstance, None)
        print(result)
        if result is not None:
            msg = MSG()
            while GetMessageW(pointer(msg), None, 0, 0):
                TranslateMessage(pointer(msg))
                DispatchMessageW(pointer(msg))


if __name__ == "__main__":
    main()
Sirius3
User
Beiträge: 17703
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt wäre es noch gut zu wissen, an welcher Stelle das Programm abstürzt. Da IDLE selbst Fenster erzeugt, kann es natürlich irgendeine Interferenz sein. Läuft es den von Kommandozeile? Sonst wirst du wahrscheinlich irgendwo einen 64-bit Pointer in 32-bit zu speichern versuchen.
Frühlingsrolle
User
Beiträge: 4
Registriert: Donnerstag 30. April 2020, 06:59

Es scheint als wäre die MSG-Struktur zum Teil dafür verantwortlich gewesen. Das Feld DWORD lPrivate hat am Ende gefehlt und nun funktioniert das Skript scheinbar mit Python 3.6.1 (64-bit) IDLE und Python 3.6.2 (32-bit) IDLE.
Probleme ergeben sich noch mit der Entwicklungsumgebung PyCharm Community Edition 2020.1, denn dort stürzt die Anwendung ab, sobald das erzeugte Fenster skaliert wird.
Je nach Interpreter wird der Prozess mit den Codes 0xC0000005 (32-bit) und 0xC000041D (64-bit) beendet.
- Läuft es den von Kommandozeile?
- Sonst wirst du wahrscheinlich irgendwo einen 64-bit Pointer in 32-bit zu speichern versuchen
Wie geht das?
Antworten