7
votes

Python3 Cype Creewindowex Exemple simple

J'ai googlé depuis un certain temps mais je n'ai pas trouvé d'exemple simple de Python3 Ctypes et de l'API Win32 pour créer et montrer une fenêtre. S'il vous plaît, signalez-moi à bon lien ou à afficher le code ici.

Merci d'avance!


0 commentaires

3 Réponses :


10
votes

Ceci est très facile à voir avec le module Win32Gui et ses amis, Win32API et Win32Con. Il n'est pas nécessaire d'écrire vos propres emballages CTTYPES vers l'API Windows. L'application la plus simple de style Petzold sort quelque chose comme ceci:

import win32api, win32con, win32gui

class MyWindow:

    def __init__(self):
        win32gui.InitCommonControls()
        self.hinst = win32api.GetModuleHandle(None)
        className = 'MyWndClass'
        message_map = {
            win32con.WM_DESTROY: self.OnDestroy,
        }
        wc = win32gui.WNDCLASS()
        wc.style = win32con.CS_HREDRAW | win32con.CS_VREDRAW
        wc.lpfnWndProc = message_map
        wc.lpszClassName = className
        win32gui.RegisterClass(wc)
        style = win32con.WS_OVERLAPPEDWINDOW
        self.hwnd = win32gui.CreateWindow(
            className,
            'My win32api app',
            style,
            win32con.CW_USEDEFAULT,
            win32con.CW_USEDEFAULT,
            300,
            300,
            0,
            0,
            self.hinst,
            None
        )
        win32gui.UpdateWindow(self.hwnd)
        win32gui.ShowWindow(self.hwnd, win32con.SW_SHOW)

    def OnDestroy(self, hwnd, message, wparam, lparam):
        win32gui.PostQuitMessage(0)
        return True

w = MyWindow()
win32gui.PumpMessages()


8 commentaires

La version Python est 3.2 et j'obtiens Importerror: Aucun module nommé Message d'erreur Win32Con. Il semble qu'il n'y ait pas de modules Win32API, Win32Con, Win32Gui


Vous ne l'avez tout simplement pas installé. Obtenez-le d'ici: sourceforge.net/projects/pywin32/files/pywin32/build216 < / a>


dépend de quelle distribution. Mon activestate 2.x viens avec elle, mais l'acteur 3.x ne le fait pas. Vous vivez la vie sur le bord de la saignement avec Python 3.x, toujours plus susceptibles de courir dans des rides comme celle-ci. Mais il semble prometteur de voler sur 3.x.


Je n'ai pas pu faire du travail Pywin32 sur quoi que ce soit d'autre que Anaconda (qui entre elle), d'autres tentatives de py27, 32 et 34 n'ont chargé que les modules binaires la première course, le cas échéant, c'est pourquoi j'ai posté une solution indigène sur Pywin32.


@TCLL PIP Installation PYPIWIN32


Merci, mais tbh, il est un peu tardif, j'ai déjà pris ma décision de supprimer Pywin32 sur la libération de Python32 en raison de modules natifs déjà disponibles _winapi , ctypes.windll.user32 , etc ... semble juste un peu inutile d'utiliser une extension quand il y a déjà une fonctionnalité native Ykno :)


@Tcll Ce n'est pas ce que vous avez dit auparavant. Vous avez dit que vous ne pouviez pas l'installer. Ne pas avoir à traduire les fichiers d'en-tête Win32 est certainement pratique, mais si le masocish est votre chose ... Pour être juste, la programmation RAW Win32 est un exercice de masocish dans n'importe quelle langue, mais Python est particulièrement douloureux pour cela.


Je l'aurais installé sur PY27, 32 et 34, comme indiqué ci-dessus (j'avais également tenté PY35, mais je n'ai jamais réussi), et je crois que Pip était la méthode la plus réussie ... Je n'ai jamais eu de travailler avec PY27 Comme il a toujours dit que cela ne pouvait pas trouver les fichiers binaires, mais pour Py3, cela fonctionnerait bien la première exécution, puis ne manquerait pas de charger les fichiers binaires sur toutes les exécutions suivantes.



5
votes

a trouvé ce joli petit bibelot et pris le temps de le faire fonctionner sur rien que la bibliothèque standard de Vanilla Python 3.4.0:
(Pour ceux qui souhaitent utiliser des indigènes sur Pywin32)
http://code.activestate.com/ Recettes / 208699-Calling-Windows-API-UTIL-CTTYPES-API-WIN32CON /

import sys
from ctypes import *

kernel32 = windll.kernel32
user32 = windll.user32
gdi32 = windll.gdi32

NULL = 0
CW_USEDEFAULT = -2147483648
IDI_APPLICATION = 32512
WS_OVERLAPPEDWINDOW = 13565952

CS_HREDRAW = 2
CS_VREDRAW = 1

IDC_ARROW = 32512
WHITE_BRUSH = 0

SW_SHOWNORMAL = 1

WNDPROC = WINFUNCTYPE(c_long, c_int, c_uint, c_int, c_int)

class WNDCLASS(Structure):
    _fields_ = [('style', c_uint),
                ('lpfnWndProc', WNDPROC),
                ('cbClsExtra', c_int),
                ('cbWndExtra', c_int),
                ('hInstance', c_int),
                ('hIcon', c_int),
                ('hCursor', c_int),
                ('hbrBackground', c_int),
                ('lpszMenuName', c_char_p),
                ('lpszClassName', c_char_p)]

class RECT(Structure):
    _fields_ = [('left', c_long),
                ('top', c_long),
                ('right', c_long),
                ('bottom', c_long)]

class PAINTSTRUCT(Structure):
    _fields_ = [('hdc', c_int),
                ('fErase', c_int),
                ('rcPaint', RECT),
                ('fRestore', c_int),
                ('fIncUpdate', c_int),
                ('rgbReserved', c_char * 32)]

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

class MSG(Structure):
    _fields_ = [('hwnd', c_int),
                ('message', c_uint),
                ('wParam', c_int),
                ('lParam', c_int),
                ('time', c_int),
                ('pt', POINT)]

def ErrorIfZero(handle):
    if handle == 0:
        raise WinError
    else:
        return handle

def MainWin():
    global NULL
    CreateWindowEx          = user32.CreateWindowExA
    CreateWindowEx.argtypes = [c_int, c_char_p, c_char_p, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int, c_int]
    CreateWindowEx.restype  = ErrorIfZero

    # Define Window Class
    wndclass = WNDCLASS()
    wndclass.style          = CS_HREDRAW | CS_VREDRAW
    wndclass.lpfnWndProc    = WNDPROC(WndProc)
    wndclass.cbClsExtra = wndclass.cbWndExtra = 0
    wndclass.hInstance      = kernel32.GetModuleHandleA(c_int(NULL))
    wndclass.hIcon          = user32.LoadIconA(c_int(NULL), c_int(IDI_APPLICATION))
    wndclass.hCursor        = user32.LoadCursorA(c_int(NULL), c_int(IDC_ARROW))
    wndclass.hbrBackground  = gdi32.GetStockObject(c_int(WHITE_BRUSH))
    wndclass.lpszMenuName   = None
    wndclass.lpszClassName  = b"MainWin"
    # Register Window Class
    if not user32.RegisterClassA(byref(wndclass)):
        raise WinError()
    # Create Window
    hwnd = CreateWindowEx(0,
                          wndclass.lpszClassName,
                          b"Python Window",
                          WS_OVERLAPPEDWINDOW,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          CW_USEDEFAULT,
                          NULL,
                          NULL,
                          wndclass.hInstance,
                          NULL)
    # Show Window
    user32.ShowWindow(c_int(hwnd), c_int(SW_SHOWNORMAL))
    user32.UpdateWindow(c_int(hwnd))
    # Pump Messages
    msg = MSG()
    pMsg = pointer(msg)
    NULL = c_int(NULL)

    while user32.GetMessageA( pMsg, NULL, 0, 0) != 0:
        user32.TranslateMessage(pMsg)
        user32.DispatchMessageA(pMsg)

    return msg.wParam

WM_PAINT = 15
WM_DESTROY = 2

DT_SINGLELINE = 32
DT_CENTER = 1
DT_VCENTER = 4
def WndProc(hwnd, message, wParam, lParam):
    ps = PAINTSTRUCT()
    rect = RECT()

    if message == WM_PAINT:
        hdc = user32.BeginPaint(c_int(hwnd), byref(ps))
        user32.GetClientRect(c_int(hwnd), byref(rect))
        user32.DrawTextA(c_int(hdc),
                         b"Python Powered Windows" ,
                         c_int(-1), byref(rect), 
                         DT_SINGLELINE|DT_CENTER|DT_VCENTER)
        user32.EndPaint(c_int(hwnd), byref(ps))
        return 0
    elif message == WM_DESTROY:
        user32.PostQuitMessage(0)
        return 0

    return user32.DefWindowProcA(c_int(hwnd), c_int(message), c_int(wParam), c_int(lParam))

if __name__=='__main__':
    sys.exit(MainWin())


3 commentaires

J'aimerais utiliser ce code mais je reçois une erreur avec Python 3.8 à Pycharm 2020.1: Oserror: [WinError 87] Mauvais paramètre. (Traduit de l'allemand). Cela semble être lié à la ligne élever WinError () mais le problème réel est que user32.registerclassa (wndclass) retourne false .


@Ben Avez-vous trouvé une solution pour cela? Je rencontre l'erreur suivante sur Python 3.8.6: wndclass.lpszclassname = "Mainwin" TypeError: octets ou adresse entière attendue au lieu d'instance STR


Je ne me souviens pas, probablement pas.



3
votes

Voici un pur CTTYPES basé sur la réponse @TCLL portée sur "Large" API également. La version originale ne manipulait pas correctement les python 64 bits (poignées de coulée à C_int) et utilisait plus les API ANSI, qui n'est plus recommandé. Il déclare également des argtypes complètes / de reposets pour tout pour aider à attraper des erreurs de codage.

Comme vous pouvez le constater, il est beaucoup plus facile d'utiliser pywin32 à la place.

testé sur Python 2.7 32 -bit, Python 3.6 64 bits et Python 3.8 32 32 bits. xxx

 Entrez la description de l'image ici


2 commentaires

Note mineure que pywin32 n'exécute généralement pas plus d'une fois après l'installation (il ne peut pas se trouver), le meilleur moyen d'installer pywin32 est d'installer Anaconda qui vient avec un package approprié qui fonctionne à plusieurs reprises.


@Tcll Il y a une étape post-installation si elle est installée via PIP dans le sous-répertoire des scripts