lovingxiaobing 发表于 2019-2-7 14:41

Python调用Win32API写win32程序(感受一下Python无所不能!!!)



来感受一下"Python无所不能"!!!

通过"ctypes"模块间接的调用win32api


代码中会用到的一些ctypes提供的功能:
。基础变量类型
。结构体
。指针
。回调函数
。ctypes提供的win32SDK的变量类型
。等等


下面的Demo会以使用opengl画图的方式展示上面提及的一些基本的功能。


先上图给大家欣赏欣赏~~~



还可以吧,嘻嘻


下面是代码,如果大家COPY了不能运行,那就下载附件吧,Python对空白符敏感


#coding:utf-8

#*****************************************************************
__author__ = "lovingxiaobing|小冰哟"
__email__= "lovingxiaobing@qq.com"
__note__   = "Python 写 Win32GUI 程序 (Python无所不能!!!)\n"\
             "用到user32.dll|kernel32.dll|opengl32.dll|gdi32.dll\n"\
             "通过ctypes内建模块间接调用Win32API"
#*****************************************************************

import sys
import ctypes
from ctypes.wintypes import *

windll = ctypes.windll

####################################################################################################################################
## variable types ##
_LRESULT = ctypes.c_long
_HCURSOR = ctypes.c_void_p
_LPMSG = ctypes.c_void_p
_LPWNDCLASSA = ctypes.c_void_p
_ULONG_PTR = LPVOID
_LPPAINTSTRUCT = LPVOID
_ARGB = DWORD
_HGLRC = LPVOID

WNDPROC = ctypes.WINFUNCTYPE(_LRESULT, HWND, UINT, WPARAM, LPARAM,)
####################################################################################################################################

## structure ##
### WNDCLASSA ##
class WNDCLASSA(ctypes.Structure):
    _fields_ = [
      ("style",       UINT),
      ("lpfnWndProc", WNDPROC),
      ("cbClsExtra",INT),
      ("cbWndExtra",INT),
      ("hInstance",   HINSTANCE),
      ("hIcon",       HICON),
      ("hCursor",   _HCURSOR),
      ("hbrBackground", HBRUSH),
      ("lpszMenuName",LPCSTR),
      ("lpszClassName", LPCSTR)
    ]


class PIXELFORMATDESCRIPTOR(ctypes.Structure):
    _fields_ = [
      ("nSize",         WORD),
      ("nVersion",      WORD),
      ("dwFlags",         DWORD),
      ("iPixelType",      BYTE),
      ("cColorBits",      BYTE),
      ("cRedBits",      BYTE),
      ("cRedShift",       BYTE),
      ("cGreenBits",      BYTE),
      ("cGreenShift",   BYTE),
      ("cBlueBits",       BYTE),
      ("cBlueShift",      BYTE),
      ("cAlphaBits",      BYTE),
      ("cAlphaShift",   BYTE),
      ("cAccumBits",      BYTE),
      ("cAccumRedBits",   BYTE),
      ("cAccumGreenBits", BYTE),
      ("cAccumBlueBits",BYTE),
      ("cAccumAlphaBits", BYTE),
      ("cDepthBits",      BYTE),
      ("cStencilBits",    BYTE),
      ("cAuxBuffers",   BYTE),
      ("iLayerType",      BYTE),
      ("bReserved",       BYTE),
      ("dwLayerMask",   DWORD),
      ("dwVisibleMask",   DWORD),
      ("dwDamageMask",    DWORD)
    ]

####################################################################################################################################
## kernel32.dll ##
### kernel32.dll exports ##
GetModuleHandle = windll.kernel32.GetModuleHandleA
GetModuleHandle.restype = HMODULE

####################################################################################################################################
## user32.dll ##
user32 = windll.LoadLibrary("user32.dll")
### user32.dll exports ##
#窗口类注册函数
RegisterClass = user32.RegisterClassA
RegisterClass.argtypes = (_LPWNDCLASSA,)
RegisterClass.restype = ATOM

#窗口显示函数
ShowWindow = user32.ShowWindow
ShowWindow.argtypes = (HWND, INT,)

#发送窗口线程结束消息
PostQuitMessage = user32.PostQuitMessage
PostQuitMessage.argtypes = (INT,)

#默认处理窗口过程 函数
DefWindowProc = user32.DefWindowProcA
DefWindowProc.argtypes = (HWND, UINT, WPARAM, LPARAM,)
DefWindowProc.restype = _LRESULT

#创建窗口函数
CreateWindowEx = user32.CreateWindowExA
CreateWindowEx.restype = HWND

#从消息队列获取消息 函数
GetMessage = user32.GetMessageA
GetMessage.argtypes = (_LPMSG, HWND, WPARAM, LPARAM,)
GetMessage.restype = BOOL

#下面是一些消息加工以及派发给窗口的 函数
TranslateMessage = user32.TranslateMessage
TranslateMessage.argtypes = (_LPMSG,)
DispatchMessage = user32.DispatchMessageA
DispatchMessage.argtypes = (_LPMSG,)

#加载窗口图标
LoadIcon = user32.LoadIconA
LoadIcon.argtypes = (HINSTANCE, LPCSTR,)
LoadIcon.restype = HICON

#加载窗口鼠标指针
LoadCursor = user32.LoadCursorA
LoadCursor.argtypes = (HINSTANCE, LPCSTR,)
LoadCursor.restype = _HCURSOR

#收到WM_PAINT后处理函数
BeginPaint = user32.BeginPaint
BeginPaint.argtypes = (HWND, _LPPAINTSTRUCT,)
BeginPaint.restype = HDC
EndPaint = user32.EndPaint
EndPaint.argtypes = (HWND, _LPPAINTSTRUCT,)
EndPaint.restype = HDC

GetDC = user32.GetDC
GetDC.argtypes = (HWND,)
GetDC.restype = HDC

ReleaseDC = user32.ReleaseDC
ReleaseDC.argtypes = (HWND, HDC,)
ReleaseDC.restype = INT

####################################################################################################################################
## opengl32.dll ##
opengl32 = windll.LoadLibrary("opengl32.dll")

wglCreateContext = opengl32.wglCreateContext
wglCreateContext.argtypes = (HDC,)
wglCreateContext.restype = _HGLRC

wglMakeCurrent = opengl32.wglMakeCurrent
wglMakeCurrent.argtypes = (HDC, _HGLRC,)
wglMakeCurrent.restype = BOOL

wglDeleteContext = opengl32.wglDeleteContext
wglDeleteContext.argtypes = (_HGLRC,)
wglDeleteContext.restype = BOOL

glClearColor = opengl32.glClearColor
glClearColor.argtypes = (FLOAT, FLOAT, FLOAT, FLOAT,)

glClear = opengl32.glClear
glClear.argtypes = (UINT,)

glBegin = opengl32.glBegin
glBegin.argtypes = (UINT,)

glEnd = opengl32.glEnd

glColor3f = opengl32.glColor3f
glColor3f.argtypes = (FLOAT, FLOAT, FLOAT,)

glColor4f = opengl32.glColor4f
glColor4f.argtypes = (FLOAT, FLOAT, FLOAT, FLOAT,)

glVertex2f = opengl32.glVertex2f
glVertex2f.argtypes = (FLOAT, FLOAT,)

glEnable = opengl32.glEnable
glEnable.argtypes = (UINT,)

glDisable = opengl32.glDisable
glDisable.argtypes = (UINT,)

glBlendFunc = opengl32.glBlendFunc
glBlendFunc.argtypes = (UINT, UINT,)

glHint = opengl32.glHint
glHint.argtypes = (UINT, UINT,)

glViewport = opengl32.glViewport
glViewport.argtypes = (INT, INT, INT, INT,)

####################################################################################################################################
## gdi32.dll ##
gdi32 = windll.LoadLibrary("gdi32.dll")

SetPixelFormat = gdi32.SetPixelFormat
SetPixelFormat.argtypes = (HDC, INT, ctypes.POINTER(PIXELFORMATDESCRIPTOR),)
SetPixelFormat.restype = BOOL

ChoosePixelFormat = gdi32.ChoosePixelFormat
ChoosePixelFormat.argtypes = (HDC, ctypes.POINTER(PIXELFORMATDESCRIPTOR),)
ChoosePixelFormat.restype = INT

SwapBuffers = gdi32.SwapBuffers
SwapBuffers.argtypes = (HDC,)
SwapBuffers.restype = BOOL

####################################################################################################################################
## macro ##
NULL = None
FALSE = BOOL(0)
TRUE = BOOL(1)

SW_SHOWDEFAULT = 0xA

CS_VREDRAW = 0x0001
CS_HREDRAW = 0x0002

WS_OVERLAPPED = 0x00000000
WS_SYSMENU = 0x00080000
WS_SIZEBOX = 0x00040000

CW_USEDEFAULT = 0x80000000

COLOR_BACKGROUND = 0x00000001

WM_DESTROY = 0x0002
WM_CREATE = 0x0001
WM_PAINT = 0x000F
WM_SIZE = 0x0005

IDI_APPLICATION = 32512
IDC_ARROW = 32512

'''
AlphaShift= 24
RedShift    = 16
GreenShift= 8
BlueShift   = 0
MakeARGB = lambda a,r,g,b: ((b)<<BlueShift)|((g)<<GreenShift)|((r)<<RedShift)|((a)<<AlphaShift)
'''

MAKEINTRESOURCE = lambda v:LPCSTR(v)
ZeroMemory = lambda addr,nsize: ctypes.memset(addr, 0, nsize)
LOWORD = lambda n: n&0xffff
HIWORD = lambda m: LOWORD(m>>0x10)

PFD_DRAW_TO_WINDOW = 0x00000004
PFD_SUPPORT_OPENGL = 0x00000020
PFD_DOUBLEBUFFER   = 0x00000001
PFD_TYPE_RGBA = 0
PFD_MAIN_PLANE = 0

GL_COLOR_BUFFER_BIT = 0x00004000
GL_TRIANGLES = 0x0004
GL_LINE_LOOP = 0x0002
GL_BLEND = 0x0BE2
GL_SRC_ALPHA = 0x0302
GL_ONE_MINUS_SRC_ALPHA = 0x0303
GL_LINE_SMOOTH = 0x0B20
GL_NICEST = 0x1102
####################################################################################################################################

## globals ##
g_ClassName = ctypes.create_string_buffer("SupriseWindowByPythonCoding".encode('gbk'))
g_WindowTitle = ctypes.create_string_buffer("嘤嘤嘤窗口".encode('gbk'))
g_hwnd = NULL
g_border_width = 640
g_border_height = 640

g_hwnd = HWND(NULL)
g_hdc = HDC(NULL)
g_hrc = _HGLRC(NULL)
####################################################################################################################################

def InitAppliction(hInstance):
    global WindowProc
    wndcls = WNDCLASSA(
      lpszClassName = ctypes.addressof(g_ClassName),
      lpfnWndProc = WindowProc,
      style = CS_VREDRAW|CS_HREDRAW,
      cbClsExtra = 0,
      cbWndExtra = 0,
      hInstance = hInstance,
      hIcon = LoadIcon(NULL, MAKEINTRESOURCE(IDI_APPLICATION)),
      hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)),
      hbrBackground = COLOR_BACKGROUND,
      lpszMenuName = LPCSTR(NULL)
    )

    return True if RegisterClass(ctypes.addressof(wndcls)) else False

####################################################################################################################################

#主函数
def WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow):
    if False == InitAppliction(hInstance):
      raise ctypes.WinError("Last Error Code: %d" % (ctypes.GetLastError()))

    hwnd = CreateWindowEx(
      0,
      ctypes.addressof(g_ClassName),
      ctypes.addressof(g_WindowTitle),
      WS_OVERLAPPED|WS_SYSMENU|WS_SIZEBOX,
      CW_USEDEFAULT, CW_USEDEFAULT,
      g_border_width, g_border_height,
      NULL, NULL,
      hInstance,
      NULL
    )

    if NULL == hwnd:
      raise ctypes.WinError("Last Error Code: %d" % (ctypes.GetLastError()))
   
    ShowWindow(hwnd, nCmdShow)

    messages = MSG()
    lpmessages = ctypes.addressof(messages)

    #消息循环
    while GetMessage(lpmessages, NULL, 0, 0):
      TranslateMessage(lpmessages)
      DispatchMessage(lpmessages)
   
    return messages.wParam

####################################################################################################################################
# 收到重绘消息响应函数
def OnPaint():
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glClear(GL_COLOR_BUFFER_BIT)

    # 线条抗锯齿
    #glEnable(GL_LINE_SMOOTH)
    #glHint(GL_LINE_SMOOTH, GL_NICEST)

    # 混合(透明)
    glEnable(GL_BLEND)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    ## 画两个叠在一起的三角形
    glBegin(GL_TRIANGLES)
    glColor3f(1.0, 0.0, 0.0)
    glVertex2f(0.0, 1.0)

    glColor3f(0.0, 1.0, 0.0)
    glVertex2f(0.87, -0.5)

    glColor3f(0.0, 0.0, 1.0)
    glVertex2f(-0.87, -0.5)
    glEnd()

    glBegin(GL_TRIANGLES)
    glColor4f(1.0, 0.0, 0.0, 0.5)
    glVertex2f(0.87, 0.5)

    glColor4f(0.0, 0.0, 1.0, 0.5)
    glVertex2f(-0.87, 0.5)

    glColor4f(0.0, 1.0, 0.0, 0.5)
    glVertex2f(0.0, -1.0)
    glEnd()
    ## ***********
    glDisable(GL_BLEND)

    ## 画六边形彩色边框
    glBegin(GL_LINE_LOOP)

    glColor3f(1.0, 0.0, 0.0)
    glVertex2f(0.0, 1.0)

    glColor3f(0.0, 1.0, 0.0)
    glVertex2f(0.87, 0.5)

    glColor3f(0.0, 0.0, 1.0)
    glVertex2f(0.87, -0.5)

    glColor3f(1.0, 0.0, 0.0)
    glVertex2f(0.0, -1.0)

    glColor3f(0.0, 1.0, 0.0)
    glVertex2f(-0.87, -0.5)

    glColor3f(0.0, 0.0, 1.0)
    glVertex2f(-0.87, 0.5)
    glEnd()

    #glDisable(GL_LINE_SMOOTH)

    SwapBuffers(g_hdc)

####################################################################################################################################
#窗口过程函数
@ctypes.WINFUNCTYPE(_LRESULT, HWND, UINT, WPARAM, LPARAM)
def WindowProc(hwnd, message, wParam, lParam):

    if WM_PAINT == message:
      BeginPaint(hwnd, _LPPAINTSTRUCT(NULL))
      OnPaint()
      EndPaint(hwnd, _LPPAINTSTRUCT(NULL))
    elif WM_SIZE == message:
      w = LOWORD(lParam)
      h = HIWORD(lParam)
      glViewport(0, 0, w, h)
    elif WM_DESTROY == message:
      DisableOpenGL()
      PostQuitMessage(0)
    elif WM_CREATE == message:
      global g_hwnd
      g_hwnd = hwnd
      EnableOpenGL()
    else:
      return DefWindowProc(hwnd, message, wParam, lParam)
   
    return 0

####################################################################################################################################
# 初始化Opengl上下文
def EnableOpenGL():
    global g_hwnd
    global g_hdc
    global g_hrc

    g_hdc = GetDC(g_hwnd)
    iFormat = INT(0)

    pfd = PIXELFORMATDESCRIPTOR()
    ZeroMemory(ctypes.addressof(pfd), ctypes.sizeof(pfd))

    pfd.nSize = ctypes.sizeof(pfd)
    pfd.nVersion = 1
    pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER
    pfd.iPixelType = PFD_TYPE_RGBA
    pfd.cColorBits = 24
    pfd.cDepthBits = 16
    pfd.iLayerType = PFD_MAIN_PLANE

    iFormat = ChoosePixelFormat(g_hdc, ctypes.byref(pfd))
    SetPixelFormat(g_hdc, iFormat, ctypes.byref(pfd))

    g_hrc = wglCreateContext(g_hdc)
    wglMakeCurrent(g_hdc, g_hrc)

####################################################################################################################################
# 注销opengl上下文
def DisableOpenGL():
    wglMakeCurrent(NULL, NULL)
    wglDeleteContext(g_hrc)
    ReleaseDC(g_hwnd, g_hdc)

####################################################################################################################################

## 主函数入口参数(应用入口)
def ApplicationEntry():
    hInstance = GetModuleHandle(NULL)
    hPrevInstance = NULL
    lpCmdLine = sys.argv
    nCmdShow = SW_SHOWDEFAULT
    ## 调用主函数
    WinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow)

####################################################################################################################################

if "__main__" == __name__:
    ApplicationEntry()

####################################################################################################################################



祝大家新年快乐,****(暗示!!!)



lovingxiaobing 发表于 2020-9-4 01:20

shinykers 发表于 2020-2-22 11:25
楼主牛!
不过能不能做是一回事,好不好做也值得考虑啊~
请问楼主,做这个事情,是否有更简单的办法呢?

pywin32:
https://github.com/mhammond/pywin32

现在可以通过pip在线安装,也可以到它的github页下载编译好的模块。

lovingxiaobing 发表于 2019-2-9 12:33

hanlu5016 发表于 2019-2-8 15:50
这个能在win7上用不

ctypes的一个小缺陷,使用的数据类型的尺寸是32位机器的大小,但是调用的却是64位的api,这个很伤~~~~
但是32位机器上运行无问题。
小冰运行这个程序的环境是:win10 32位|python3.7.1

xu6456338 发表于 2019-2-7 15:32

nice 学习学习

加油 发表于 2019-2-7 16:08

吾爱支持 发表于 2019-2-7 16:37

感谢楼主分享……学习了。
送上小CB和祝福

hackysh 发表于 2019-2-7 17:25

成品在哪?上传啊啊

zjmowu 发表于 2019-2-7 17:31


感谢楼主分享……学习了。

绅士· 发表于 2019-2-7 17:47

楼主可以的

hanlu5016 发表于 2019-2-8 15:50

这个能在win7上用不

南川没有北鱼 发表于 2020-2-20 11:31

感谢楼主,学习一下
页: [1] 2
查看完整版本: Python调用Win32API写win32程序(感受一下Python无所不能!!!)