使用Windows API制作多个Windows的最佳/理想方法是什么?

发布于 2025-01-27 23:38:48 字数 13090 浏览 1 评论 0原文

我有一个带有一堆按钮的窗户。这些按钮上有文件的名称。当用户单击按钮时,我想打开该文件,读取它,将其写入编辑框并在屏幕上显示。我想删除所有按钮,然后制作一个编辑框。当用户按“主页”按钮时,我的程序应将其带到按钮页面。

到目前为止,我正在考虑使用DestroyWindow,然后创建一个新窗口。我不确定这是我应该做的。 (另外,我正在使用python,以防万一您想知道为什么我有python标签)

main.py

from os import listdir
from user32 import *
from button import Button
from pathlib import Path

hInst = windll.kernel32.GetModuleHandleW(0)
buttons = []

BTN_WIDTH = 300
BTN_HEIGHT = 100
LINES = 10

def window_proc(hwnd: HWND, umsg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT:
    si = SCROLLINFO()
    si_pointer = pointer(si)
    match umsg:
        case WindowMessage.CREATE:
            create_list_of_buttons(get_files(), hwnd)
        case WindowMessage.DESTROY:
            PostQuitMessage(0)
            return 0
        
        case WindowMessage.SIZE:
            height = (HIWORD(lparam))
            width = (LOWORD(lparam))

            si.cbSize = sizeof(si)
            si.fMask = ScrollInfoMessage.RANGE | ScrollInfoMessage.PAGE
            si.nMin = 0
            print(width)
            si.nMax = BTN_HEIGHT * 5 - 60
            si.nPage = 1;
            SetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer, True)

        case WindowMessage.COMMAND:
            if wparam >= 100:
                btn_clicked = ([button for button in buttons if button.hMenu == wparam])
                filename = btn_clicked[0].btn_text
                print(filename)
                rect = RECT()
                rect_p = pointer(rect)
                # print(GetClientRect(hwnd, rect_p))
                # print(rect.top, rect.bottom, rect.left, rect.right)
        case WindowMessage.VSCROLL:
            si.cbSize = sizeof(si)
            si.fMask = ScrollInfoMessage.ALL
            GetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer)

            yPos = si.nPos
            match LOWORD(wparam).value:
                case ScrollBarCommands.LINEUP:
                    si.nPos -= 1
                case ScrollBarCommands.TOP:
                    si.nPos = si.nMin
                case ScrollBarCommands.BOTTOM:
                    si.nPos = si.nMax
                case ScrollBarCommands.LINEUP:
                    si.nPos -= 1
                case ScrollBarCommands.LINEDOWN:
                    si.nPos += 1
                case ScrollBarCommands.PAGEUP:
                    si.nPos -= si.nPage
                case ScrollBarCommands.PAGEDOWN:
                    si.nPos += si.nPage
                case ScrollBarCommands.THUMBTRACK:
                    si.nPos = si.nTrackPos

            si.fMask = ScrollInfoMessage.POS
            SetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer, True)
            GetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer)
            if(si.nPos != yPos):
                ScrollWindowEx(hwnd, -0, (yPos - si.nPos), None, None, None, None, 0x0001|0x0002)
                hdwp = BeginDeferWindowPos(1)
                recent_hdwp = DeferWindowPos(hdwp, hwnd, None,  0, 0, 100, 100, 0x0020|0x0004|0x0001|0x0002)
                EndDeferWindowPos(recent_hdwp)
                UpdateWindow(hwnd)

    return DefWindowProcW(hwnd, umsg, wparam, lparam)


def create_window(className, windowName):
    wnd_main = CreateWindowExW(
        0,
        className,
        windowName,
        WindowStyles.OVERLAPPED
        | WindowStyles.CAPTION
        | WindowStyles.SYSMENU
        | WindowStyles.THICKFRAME
        | WindowStyles.MINIMIZEBOX
        | WindowStyles.MAXIMIZEBOX
        | WindowStyles.CAPTION
        | WindowStyles.VSCROLL,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        600,
        600,
        0,
        0,
        hInst,
        0,
    )
    if not wnd_main:
        print("Window Creation Falid: ", GetLastError())
        return
    return wnd_main


def get_files():
    folder_path = Path(__file__).parent / "log"
    return [file for file in listdir(folder_path) if file.endswith(".txt")]

def create_list_of_buttons(filenames: list[str], parent_window):
    """
    Makes a list of button that have the file's name as their heading
    """
    x, y = 0, 0
    for button_id, filename in enumerate(filenames, 100):
        button = Button(filename, x, y, BTN_WIDTH, BTN_HEIGHT, parent_window, button_id)
        button.create_button()
        buttons.append(button)
        y += BTN_HEIGHT

    return buttons




def main():
    wclassName = ctypes.c_wchar_p("My")
    wname = ctypes.c_wchar_p("Left")
    wndClass = WNDCLASSEXW()
    wndClass.cbSize = sizeof(WNDCLASSEXW)
    wndClass.style = ClassStyles.HREDRAW | ClassStyles.VREDRAW
    wndClass.lpfnWndProc = WNDPROC(window_proc)
    wndClass.cbClsExtra = 0
    wndClass.cbWndExtra = 0
    wndClass.hInstance = hInst
    wndClass.hIcon = 0
    wndClass.hCursor = 0
    wndClass.hBrush = windll.gdi32.GetStockObject(0)
    wndClass.lpszMenuName = 0
    wndClass.lpszClassName = wclassName
    wndClass.hIconSm = 0
    RegisterClassExW(byref(wndClass))
    wnd_main = create_window(wclassName, wname)
    ShowWindow(wnd_main, 5)
    UpdateWindow(wnd_main)

    msg = MSG()
    lpmsg = pointer(msg)
    while (GetMessageW(lpmsg, 0, 0, 0)) != 0:
        TranslateMessage(lpmsg)
        DispatchMessageW(lpmsg)


main()

user32.py

import ctypes
import enum
from ctypes import *
from ctypes.wintypes import *

WNDPROC = ctypes.WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)
LRESULT = c_long
LONG_PTR = LPARAM
CW_USEDEFAULT = 0x80000000
WNDENUMPROC = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
user32 = windll.user32


class WindowStyles(enum.IntFlag):
    BORDER = 0x00800000
    CAPTION = 0x00C00000
    CHILD = 0x40000000
    CHILDWINDOW = 0x40000000
    CLIPCHILDREN = 0x02000000
    CLIPSIBLINGS = 0x04000000
    DISABLED = 0x08000000
    DLGFRAME = 0x00400000
    GROUP = 0x00020000
    HSCROLL = 0x00100000
    ICONIC = 0x20000000
    MAXIMIZE = 0x01000000
    MAXIMIZEBOX = 0x00010000
    MINIMIZE = 0x20000000
    MINIMIZEBOX = 0x00020000
    OVERLAPPED = 0x00000000
    SYSMENU = 0x00080000
    THICKFRAME = 0x00040000
    TILED = 0x00000000
    VISIBLE = 0x10000000
    VSCROLL = 0x00200000
    SIZEBOX = 0x00040000
    TABSTOP = 0x00010000
    POPUP = 0x80000000
    TILEDWINDOW = (
        OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX
    )
    OVERLAPPEDWINDOW = (
        OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX
    )
    POPUPWINDOW = POPUP | BORDER | SYSMENU


class WindowMessage(enum.IntEnum):
    SETFOCUS = 0x0007
    KILLFOCUS = 0x0006
    ENABLE = 0x000A
    SETREDRAW = 0x000B
    SETTEXT = 0x000C
    SETFONT = 0x0030
    GETFONT = 0x0031
    GETTEXT = 0x000D
    GETTEXTLENGTH = 0x000E
    PAINT = 0x000F
    CLOSE = 0x00010
    QUIT = 0x0012
    SHOWWINDOW = 0x0018
    NULL = 0x0000
    CREATE = 0x0001
    DESTROY = 0x0002
    MOVE = 0x0003
    SIZE = 0x0005
    ACTIVATE = 0x0006
    COMMAND = 0x0111
    NOTIFY = 0x004E
    VSCROLL = 0x0115


class ClassStyles(enum.IntFlag):
    VREDRAW = 0x0001
    HREDRAW = 0x0002
    DBLCLKS = 0x0008
    OWNDC = 0x0020
    CLASSDC = 0x0040
    PARENTDC = 0x0080
    NOCLOSE = 0x0200
    SAVEBITS = 0x0800
    BYTEALIGNCLIENT = 0x1000
    BYTEALIGNWINDOW = 0x2000
    GLOBALCLASS = 0x4000


class ButtonStyle(enum.IntFlag):
    PUSHBUTTON = 0x00000000
    DEFPUSHBUTTON = 0x00000001
    CHECKBOX = 0x00000002
    AUTOCHECKBOX = 0x00000003
    RADIOBUTTON = 0x00000004
    _3STATE = 0x00000005
    AUTO3STATE = 0x00000006
    GROUPBOX = 0x00000007
    USERBUTTON = 0x00000008
    AUTORADIOBUTTON = 0x00000009
    PUSHBOX = 0x0000000A
    OWNERDRAW = 0x0000000B
    TYPEMASK = 0x0000000F
    LEFTTEXT = 0x00000020
    TEXT = 0x00000000
    ICON = 0x00000040
    BITMAP = 0x00000080
    LEFT = 0x00000100
    RIGHT = 0x00000200
    CENTER = 0x00000300
    TOP = 0x00000400
    BOTTOM = 0x00000800
    VCENTER = 0x00000C00
    PUSHLIKE = 0x00001000
    MULTILINE = 0x00002000
    NOTIFY = 0x00004000
    FLAT = 0x00008000
    RIGHTBUTTON = LEFTTEXT


class WNDCLASSEXW(Structure):
    _fields_ = [
        ("cbSize", c_uint),
        ("style", c_uint),
        ("lpfnWndProc", WNDPROC),
        ("cbClsExtra", c_int),
        ("cbWndExtra", c_int),
        ("hInstance", HANDLE),
        ("hIcon", HANDLE),
        ("hCursor", HANDLE),
        ("hBrush", HANDLE),
        ("lpszMenuName", LPCWSTR),
        ("lpszClassName", LPCWSTR),
        ("hIconSm", HANDLE),
    ]


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


class GetWindowLong(enum.IntEnum):
    EXSTYLE = -20
    HINSTANCE = -6
    HWNDPARENT = -8
    ID = -12
    STYLE = -16
    USERDATA = -21
    WNDPROC = -4


class SCROLLINFO(Structure):
    _fields_ = [
        ("cbSize", UINT),
        ("fMask", UINT),
        ("nMin", c_int),
        ("nMax", c_int),
        ("nPage", UINT),
        ("nPos", c_int),
        ("nTrackPos", c_int),
    ]


class ScrollInfoMessage(enum.IntEnum):
    RANGE = 0x0001
    PAGE = 0x0002
    POS = 0x0004
    DISABLENOSCROLL = 0x0008
    TRACKPOS = 0x0010
    ALL = RANGE | PAGE | POS | TRACKPOS


class ScrollBarConstants(enum.IntEnum):
    HORZ = 0
    VERT = 1
    CTL = 2
    BOTH = 3


class ScrollBarCommands(enum.IntEnum):
    LINEUP = 0
    LINELEFT = 0
    LINEDOWN = 1
    LINERIGHT = 1
    PAGEUP = 2
    PAGELEFT = 2
    PAGEDOWN = 3
    PAGERIGHT = 3
    THUMBPOSITION = 4
    THUMBTRACK = 5
    TOP = 6
    LEFT = 6
    BOTTOM = 7
    RIGHT = 7
    ENDSCROLL = 8


def HIWORD(l):
    return WORD((l >> 16) & 0xFFFF)


def LOWORD(l):
    return WORD(l & 0xFFFF)


LPMSG = POINTER(MSG)
LPCSCROLLINFO = POINTER(SCROLLINFO)


DefWindowProcW = user32.DefWindowProcW
DefWindowProcW.argtypes = [HWND, UINT, WPARAM, LPARAM]
DefWindowProcW.restype = LRESULT

CreateWindowExW = user32.CreateWindowExW
CreateWindowExW.argtypes = [
    DWORD,
    LPCWSTR,
    LPCWSTR,
    DWORD,
    c_int,
    c_int,
    c_int,
    c_int,
    HWND,
    HMENU,
    HINSTANCE,
    LPVOID,
]
CreateWindowExW.restype = HWND


LPWNDCLASSW = POINTER(WNDCLASSEXW)
RegisterClassExW = user32.RegisterClassExW
RegisterClassExW.argtypes = [LPWNDCLASSW]
RegisterClassExW.restype = ATOM

ShowWindow = user32.ShowWindow
ShowWindow.argtypes = [HWND, c_int]
ShowWindow.restype = BOOL

UpdateWindow = user32.UpdateWindow
UpdateWindow.argtypes = [HWND]
UpdateWindow.restype = BOOL

GetMessageW = user32.GetMessageW
GetMessageW.argtypes = [LPMSG, HWND, UINT, UINT]
GetMessageW.restype = BOOL

TranslateMessage = user32.TranslateMessage
TranslateMessage.argtypes = [LPMSG]
TranslateMessage.restype = BOOL

DispatchMessageW = user32.DispatchMessageW
DispatchMessageW.argtypes = [LPMSG]
DispatchMessageW.restype = LRESULT

PostQuitMessage = user32.PostQuitMessage
PostQuitMessage.argtypes = [c_int]
PostQuitMessage.restype = None

GetWindowLongPtrW = user32.GetWindowLongPtrW
GetWindowLongPtrW.argtypes = [HWND, c_int]
GetWindowLongPtrW.restype = LONG_PTR

GetWindow = user32.GetWindow
GetWindow.argtypes = [HWND, UINT]
GetWindow.restype = HWND

ScrollWindowEx = user32.ScrollWindowEx
ScrollWindowEx.argtypes = [HWND, c_int, c_int, LPRECT, LPRECT, HRGN, LPRECT, UINT]
ScrollWindowEx.restype = int

SetScrollInfo = user32.SetScrollInfo
SetScrollInfo.argtypes = [HWND, c_int, LPCSCROLLINFO, BOOL]
SetScrollInfo.restype = int

GetScrollInfo = user32.GetScrollInfo
GetScrollInfo.argtypes = [HWND, c_int, LPCSCROLLINFO]
GetScrollInfo.restype = BOOL

GetClientRect = user32.GetClientRect
GetClientRect.argtypes = [HWND, LPRECT]
GetClientRect.restype = BOOL

BeginDeferWindowPos = user32.BeginDeferWindowPos
BeginDeferWindowPos.argtypes = [c_int]
BeginDeferWindowPos.restype = HDWP

DeferWindowPos = user32.DeferWindowPos
DeferWindowPos.argtypes = [HDWP, HWND, HWND, c_int, c_int, c_int, c_int, c_uint]
DeferWindowPos.restype = HDWP

EndDeferWindowPos = user32.EndDeferWindowPos
EndDeferWindowPos.argtypes = [HDWP]
EndDeferWindowPos.restype = BOOL

button.py

from ctypes.wintypes import HINSTANCE, HMENU, HWND, LPCWSTR, LPVOID
from dataclasses import dataclass
from ctypes import *

from user32 import (
    ButtonStyle,
    CreateWindowExW,
    GetWindowLongPtrW,
    WindowStyles,
    GetWindowLong,
)


@dataclass
class Button:
    btn_text: LPCWSTR
    x: c_int
    y: c_int
    width: c_int
    height: c_int
    hwnd_parent: HWND
    hMenu: HMENU

    def create_button(self):
        button = CreateWindowExW(
            0,
            "BUTTON",
            self.btn_text,
            WindowStyles.TABSTOP
            | WindowStyles.VISIBLE
            | WindowStyles.CHILD
            | ButtonStyle.PUSHBUTTON,
            self.x,
            self.y,
            self.width,
            self.height,
            self.hwnd_parent,
            HMENU(self.hMenu),
            cast(
                GetWindowLongPtrW(self.hwnd_parent, GetWindowLong.HINSTANCE), HINSTANCE
            ),
            None,
        )
        return button

I have a window with a bunch of buttons. Those buttons have file's names on them. When the user clicks a button, I want to open that file, read it, write it to an edit box and display it on the screen. I would like to delete all the buttons and just make an edit box. When the user presses the home button, my program should take them to the button page.

So far, I am thinking of using DestroyWindow and then create a new window. I am not sure if this is how I am supposed to do it. (Also, I am using python, just in case you were wondering why I have the python tag)

main.py

from os import listdir
from user32 import *
from button import Button
from pathlib import Path

hInst = windll.kernel32.GetModuleHandleW(0)
buttons = []

BTN_WIDTH = 300
BTN_HEIGHT = 100
LINES = 10

def window_proc(hwnd: HWND, umsg: UINT, wparam: WPARAM, lparam: LPARAM) -> LRESULT:
    si = SCROLLINFO()
    si_pointer = pointer(si)
    match umsg:
        case WindowMessage.CREATE:
            create_list_of_buttons(get_files(), hwnd)
        case WindowMessage.DESTROY:
            PostQuitMessage(0)
            return 0
        
        case WindowMessage.SIZE:
            height = (HIWORD(lparam))
            width = (LOWORD(lparam))

            si.cbSize = sizeof(si)
            si.fMask = ScrollInfoMessage.RANGE | ScrollInfoMessage.PAGE
            si.nMin = 0
            print(width)
            si.nMax = BTN_HEIGHT * 5 - 60
            si.nPage = 1;
            SetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer, True)

        case WindowMessage.COMMAND:
            if wparam >= 100:
                btn_clicked = ([button for button in buttons if button.hMenu == wparam])
                filename = btn_clicked[0].btn_text
                print(filename)
                rect = RECT()
                rect_p = pointer(rect)
                # print(GetClientRect(hwnd, rect_p))
                # print(rect.top, rect.bottom, rect.left, rect.right)
        case WindowMessage.VSCROLL:
            si.cbSize = sizeof(si)
            si.fMask = ScrollInfoMessage.ALL
            GetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer)

            yPos = si.nPos
            match LOWORD(wparam).value:
                case ScrollBarCommands.LINEUP:
                    si.nPos -= 1
                case ScrollBarCommands.TOP:
                    si.nPos = si.nMin
                case ScrollBarCommands.BOTTOM:
                    si.nPos = si.nMax
                case ScrollBarCommands.LINEUP:
                    si.nPos -= 1
                case ScrollBarCommands.LINEDOWN:
                    si.nPos += 1
                case ScrollBarCommands.PAGEUP:
                    si.nPos -= si.nPage
                case ScrollBarCommands.PAGEDOWN:
                    si.nPos += si.nPage
                case ScrollBarCommands.THUMBTRACK:
                    si.nPos = si.nTrackPos

            si.fMask = ScrollInfoMessage.POS
            SetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer, True)
            GetScrollInfo(hwnd, ScrollBarConstants.VERT, si_pointer)
            if(si.nPos != yPos):
                ScrollWindowEx(hwnd, -0, (yPos - si.nPos), None, None, None, None, 0x0001|0x0002)
                hdwp = BeginDeferWindowPos(1)
                recent_hdwp = DeferWindowPos(hdwp, hwnd, None,  0, 0, 100, 100, 0x0020|0x0004|0x0001|0x0002)
                EndDeferWindowPos(recent_hdwp)
                UpdateWindow(hwnd)

    return DefWindowProcW(hwnd, umsg, wparam, lparam)


def create_window(className, windowName):
    wnd_main = CreateWindowExW(
        0,
        className,
        windowName,
        WindowStyles.OVERLAPPED
        | WindowStyles.CAPTION
        | WindowStyles.SYSMENU
        | WindowStyles.THICKFRAME
        | WindowStyles.MINIMIZEBOX
        | WindowStyles.MAXIMIZEBOX
        | WindowStyles.CAPTION
        | WindowStyles.VSCROLL,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        600,
        600,
        0,
        0,
        hInst,
        0,
    )
    if not wnd_main:
        print("Window Creation Falid: ", GetLastError())
        return
    return wnd_main


def get_files():
    folder_path = Path(__file__).parent / "log"
    return [file for file in listdir(folder_path) if file.endswith(".txt")]

def create_list_of_buttons(filenames: list[str], parent_window):
    """
    Makes a list of button that have the file's name as their heading
    """
    x, y = 0, 0
    for button_id, filename in enumerate(filenames, 100):
        button = Button(filename, x, y, BTN_WIDTH, BTN_HEIGHT, parent_window, button_id)
        button.create_button()
        buttons.append(button)
        y += BTN_HEIGHT

    return buttons




def main():
    wclassName = ctypes.c_wchar_p("My")
    wname = ctypes.c_wchar_p("Left")
    wndClass = WNDCLASSEXW()
    wndClass.cbSize = sizeof(WNDCLASSEXW)
    wndClass.style = ClassStyles.HREDRAW | ClassStyles.VREDRAW
    wndClass.lpfnWndProc = WNDPROC(window_proc)
    wndClass.cbClsExtra = 0
    wndClass.cbWndExtra = 0
    wndClass.hInstance = hInst
    wndClass.hIcon = 0
    wndClass.hCursor = 0
    wndClass.hBrush = windll.gdi32.GetStockObject(0)
    wndClass.lpszMenuName = 0
    wndClass.lpszClassName = wclassName
    wndClass.hIconSm = 0
    RegisterClassExW(byref(wndClass))
    wnd_main = create_window(wclassName, wname)
    ShowWindow(wnd_main, 5)
    UpdateWindow(wnd_main)

    msg = MSG()
    lpmsg = pointer(msg)
    while (GetMessageW(lpmsg, 0, 0, 0)) != 0:
        TranslateMessage(lpmsg)
        DispatchMessageW(lpmsg)


main()

user32.py

import ctypes
import enum
from ctypes import *
from ctypes.wintypes import *

WNDPROC = ctypes.WINFUNCTYPE(c_int, HWND, c_uint, WPARAM, LPARAM)
LRESULT = c_long
LONG_PTR = LPARAM
CW_USEDEFAULT = 0x80000000
WNDENUMPROC = ctypes.WINFUNCTYPE(BOOL, HWND, LPARAM)
user32 = windll.user32


class WindowStyles(enum.IntFlag):
    BORDER = 0x00800000
    CAPTION = 0x00C00000
    CHILD = 0x40000000
    CHILDWINDOW = 0x40000000
    CLIPCHILDREN = 0x02000000
    CLIPSIBLINGS = 0x04000000
    DISABLED = 0x08000000
    DLGFRAME = 0x00400000
    GROUP = 0x00020000
    HSCROLL = 0x00100000
    ICONIC = 0x20000000
    MAXIMIZE = 0x01000000
    MAXIMIZEBOX = 0x00010000
    MINIMIZE = 0x20000000
    MINIMIZEBOX = 0x00020000
    OVERLAPPED = 0x00000000
    SYSMENU = 0x00080000
    THICKFRAME = 0x00040000
    TILED = 0x00000000
    VISIBLE = 0x10000000
    VSCROLL = 0x00200000
    SIZEBOX = 0x00040000
    TABSTOP = 0x00010000
    POPUP = 0x80000000
    TILEDWINDOW = (
        OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX
    )
    OVERLAPPEDWINDOW = (
        OVERLAPPED | CAPTION | SYSMENU | THICKFRAME | MINIMIZEBOX | MAXIMIZEBOX
    )
    POPUPWINDOW = POPUP | BORDER | SYSMENU


class WindowMessage(enum.IntEnum):
    SETFOCUS = 0x0007
    KILLFOCUS = 0x0006
    ENABLE = 0x000A
    SETREDRAW = 0x000B
    SETTEXT = 0x000C
    SETFONT = 0x0030
    GETFONT = 0x0031
    GETTEXT = 0x000D
    GETTEXTLENGTH = 0x000E
    PAINT = 0x000F
    CLOSE = 0x00010
    QUIT = 0x0012
    SHOWWINDOW = 0x0018
    NULL = 0x0000
    CREATE = 0x0001
    DESTROY = 0x0002
    MOVE = 0x0003
    SIZE = 0x0005
    ACTIVATE = 0x0006
    COMMAND = 0x0111
    NOTIFY = 0x004E
    VSCROLL = 0x0115


class ClassStyles(enum.IntFlag):
    VREDRAW = 0x0001
    HREDRAW = 0x0002
    DBLCLKS = 0x0008
    OWNDC = 0x0020
    CLASSDC = 0x0040
    PARENTDC = 0x0080
    NOCLOSE = 0x0200
    SAVEBITS = 0x0800
    BYTEALIGNCLIENT = 0x1000
    BYTEALIGNWINDOW = 0x2000
    GLOBALCLASS = 0x4000


class ButtonStyle(enum.IntFlag):
    PUSHBUTTON = 0x00000000
    DEFPUSHBUTTON = 0x00000001
    CHECKBOX = 0x00000002
    AUTOCHECKBOX = 0x00000003
    RADIOBUTTON = 0x00000004
    _3STATE = 0x00000005
    AUTO3STATE = 0x00000006
    GROUPBOX = 0x00000007
    USERBUTTON = 0x00000008
    AUTORADIOBUTTON = 0x00000009
    PUSHBOX = 0x0000000A
    OWNERDRAW = 0x0000000B
    TYPEMASK = 0x0000000F
    LEFTTEXT = 0x00000020
    TEXT = 0x00000000
    ICON = 0x00000040
    BITMAP = 0x00000080
    LEFT = 0x00000100
    RIGHT = 0x00000200
    CENTER = 0x00000300
    TOP = 0x00000400
    BOTTOM = 0x00000800
    VCENTER = 0x00000C00
    PUSHLIKE = 0x00001000
    MULTILINE = 0x00002000
    NOTIFY = 0x00004000
    FLAT = 0x00008000
    RIGHTBUTTON = LEFTTEXT


class WNDCLASSEXW(Structure):
    _fields_ = [
        ("cbSize", c_uint),
        ("style", c_uint),
        ("lpfnWndProc", WNDPROC),
        ("cbClsExtra", c_int),
        ("cbWndExtra", c_int),
        ("hInstance", HANDLE),
        ("hIcon", HANDLE),
        ("hCursor", HANDLE),
        ("hBrush", HANDLE),
        ("lpszMenuName", LPCWSTR),
        ("lpszClassName", LPCWSTR),
        ("hIconSm", HANDLE),
    ]


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


class GetWindowLong(enum.IntEnum):
    EXSTYLE = -20
    HINSTANCE = -6
    HWNDPARENT = -8
    ID = -12
    STYLE = -16
    USERDATA = -21
    WNDPROC = -4


class SCROLLINFO(Structure):
    _fields_ = [
        ("cbSize", UINT),
        ("fMask", UINT),
        ("nMin", c_int),
        ("nMax", c_int),
        ("nPage", UINT),
        ("nPos", c_int),
        ("nTrackPos", c_int),
    ]


class ScrollInfoMessage(enum.IntEnum):
    RANGE = 0x0001
    PAGE = 0x0002
    POS = 0x0004
    DISABLENOSCROLL = 0x0008
    TRACKPOS = 0x0010
    ALL = RANGE | PAGE | POS | TRACKPOS


class ScrollBarConstants(enum.IntEnum):
    HORZ = 0
    VERT = 1
    CTL = 2
    BOTH = 3


class ScrollBarCommands(enum.IntEnum):
    LINEUP = 0
    LINELEFT = 0
    LINEDOWN = 1
    LINERIGHT = 1
    PAGEUP = 2
    PAGELEFT = 2
    PAGEDOWN = 3
    PAGERIGHT = 3
    THUMBPOSITION = 4
    THUMBTRACK = 5
    TOP = 6
    LEFT = 6
    BOTTOM = 7
    RIGHT = 7
    ENDSCROLL = 8


def HIWORD(l):
    return WORD((l >> 16) & 0xFFFF)


def LOWORD(l):
    return WORD(l & 0xFFFF)


LPMSG = POINTER(MSG)
LPCSCROLLINFO = POINTER(SCROLLINFO)


DefWindowProcW = user32.DefWindowProcW
DefWindowProcW.argtypes = [HWND, UINT, WPARAM, LPARAM]
DefWindowProcW.restype = LRESULT

CreateWindowExW = user32.CreateWindowExW
CreateWindowExW.argtypes = [
    DWORD,
    LPCWSTR,
    LPCWSTR,
    DWORD,
    c_int,
    c_int,
    c_int,
    c_int,
    HWND,
    HMENU,
    HINSTANCE,
    LPVOID,
]
CreateWindowExW.restype = HWND


LPWNDCLASSW = POINTER(WNDCLASSEXW)
RegisterClassExW = user32.RegisterClassExW
RegisterClassExW.argtypes = [LPWNDCLASSW]
RegisterClassExW.restype = ATOM

ShowWindow = user32.ShowWindow
ShowWindow.argtypes = [HWND, c_int]
ShowWindow.restype = BOOL

UpdateWindow = user32.UpdateWindow
UpdateWindow.argtypes = [HWND]
UpdateWindow.restype = BOOL

GetMessageW = user32.GetMessageW
GetMessageW.argtypes = [LPMSG, HWND, UINT, UINT]
GetMessageW.restype = BOOL

TranslateMessage = user32.TranslateMessage
TranslateMessage.argtypes = [LPMSG]
TranslateMessage.restype = BOOL

DispatchMessageW = user32.DispatchMessageW
DispatchMessageW.argtypes = [LPMSG]
DispatchMessageW.restype = LRESULT

PostQuitMessage = user32.PostQuitMessage
PostQuitMessage.argtypes = [c_int]
PostQuitMessage.restype = None

GetWindowLongPtrW = user32.GetWindowLongPtrW
GetWindowLongPtrW.argtypes = [HWND, c_int]
GetWindowLongPtrW.restype = LONG_PTR

GetWindow = user32.GetWindow
GetWindow.argtypes = [HWND, UINT]
GetWindow.restype = HWND

ScrollWindowEx = user32.ScrollWindowEx
ScrollWindowEx.argtypes = [HWND, c_int, c_int, LPRECT, LPRECT, HRGN, LPRECT, UINT]
ScrollWindowEx.restype = int

SetScrollInfo = user32.SetScrollInfo
SetScrollInfo.argtypes = [HWND, c_int, LPCSCROLLINFO, BOOL]
SetScrollInfo.restype = int

GetScrollInfo = user32.GetScrollInfo
GetScrollInfo.argtypes = [HWND, c_int, LPCSCROLLINFO]
GetScrollInfo.restype = BOOL

GetClientRect = user32.GetClientRect
GetClientRect.argtypes = [HWND, LPRECT]
GetClientRect.restype = BOOL

BeginDeferWindowPos = user32.BeginDeferWindowPos
BeginDeferWindowPos.argtypes = [c_int]
BeginDeferWindowPos.restype = HDWP

DeferWindowPos = user32.DeferWindowPos
DeferWindowPos.argtypes = [HDWP, HWND, HWND, c_int, c_int, c_int, c_int, c_uint]
DeferWindowPos.restype = HDWP

EndDeferWindowPos = user32.EndDeferWindowPos
EndDeferWindowPos.argtypes = [HDWP]
EndDeferWindowPos.restype = BOOL

button.py

from ctypes.wintypes import HINSTANCE, HMENU, HWND, LPCWSTR, LPVOID
from dataclasses import dataclass
from ctypes import *

from user32 import (
    ButtonStyle,
    CreateWindowExW,
    GetWindowLongPtrW,
    WindowStyles,
    GetWindowLong,
)


@dataclass
class Button:
    btn_text: LPCWSTR
    x: c_int
    y: c_int
    width: c_int
    height: c_int
    hwnd_parent: HWND
    hMenu: HMENU

    def create_button(self):
        button = CreateWindowExW(
            0,
            "BUTTON",
            self.btn_text,
            WindowStyles.TABSTOP
            | WindowStyles.VISIBLE
            | WindowStyles.CHILD
            | ButtonStyle.PUSHBUTTON,
            self.x,
            self.y,
            self.width,
            self.height,
            self.hwnd_parent,
            HMENU(self.hMenu),
            cast(
                GetWindowLongPtrW(self.hwnd_parent, GetWindowLong.HINSTANCE), HINSTANCE
            ),
            None,
        )
        return button

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文