win32more

repository·main·Indexed 42 days ago

https://github.com/ynkdir/py-win32more

Python bindings for the Windows API and WinUI 3, generated from Microsoft metadata. Version 0.8.1 allows developers to interface directly with Windows system components, including support for Win2D graphics operations via CanvasDevice, CanvasBitmap, and CanvasDrawingSession, as well as guidance for creating packaged MSIX/Appx applications.

Tokens
67.8K
Snippets
213
Records
340
Agent score
53%

What's inside win32more

  1. Create a packaged application for Win32more

    main

    Some Windows APIs (such as the Windows AI API) require a package identity at runtime. To use these, you must package your Python application as an MSIX/Appx package. This process involves downloading a standalone Python package, creating an AppxManifest.xml, and registering the package on your system.

    For detailed guidance on the underlying Windows requirements, refer to Generating MSIX package components.

  2. Create a WinUI 3 application with XamlApplication

    main

    To build a WinUI 3 application, subclass XamlApplication and implement the OnLaunched method. Use win32more.winui3.XamlApplication.Start(App) to run the application loop.

    Basic structure:

    from win32more.Microsoft.UI.Xaml import Window
    from win32more.winui3 import XamlApplication
    
    class App(XamlApplication):
        def OnLaunched(self, args):
            win = Window()
            win.Activate()
    
    XamlApplication.Start(App)
    from win32more.Microsoft.UI.Xaml import Window
    from win32more.winui3 import XamlApplication
    
    class App(XamlApplication):
        def OnLaunched(self, args):
            win = Window()
            win.Activate()
    
    XamlApplication.Start(App)
  3. Install and manage packaged applications

    main

    To install your packaged application, you must first enable Developer Mode on Windows 11. Once enabled, you can register the package using PowerShell.

    Install/Register Package

    Use Add-AppxPackage -Register pointing to your manifest file.

    Get Package Information

    Use Get-AppxPackage with the package identity to verify installation details.

    Get AppID

    Use Get-StartApps to find the specific AppID required for starting the application.

    Uninstall Package

    Use Remove-AppxPackage with the full package name.

    # Install
    Add-AppxPackage -Register testapp\AppxManifest.xml
    
    # Get Info
    Get-AppxPackage Win32more.TestApp
    
    # Get AppID
    Get-StartApps TestApp
    
    # Uninstall
    Remove-AppxPackage Win32more.TestApp_1.0.0.0_x64__x22gc0rg6bp3w
  4. Install the win32more library

    main

    Install the core win32more library using pip:

    python -m pip install win32more

    Version Pinning for Compatibility: To ensure compatibility with specific versions of the Windows App SDK on machines with older SDK versions, it is recommended to pin the following packages to a specific version (replace VERSION with your target minimum version from NuGet):

    • win32more-Microsoft.Windows.SDK.Win32Metadata == 0.8.VERSION
    • win32more-Microsoft.Windows.WDK.Win32Metadata == 0.8.VERSION
    • win32more-Microsoft.Windows.SDK.Contracts == 0.8.VERSION
    • win32more-Microsoft.WindowsAppSDK == 0.8.VERSION
    • win32more-Microsoft.Web.WebView2 == 0.8.VERSION
    • win32more-Microsoft.Graphics.Win2D == 0.8.VERSION
  5. Download and prepare a standalone Python package

    main

    To prepare the environment for a packaged application, you can either install a standalone Python package using pymanager or build a self-contained package using the provided build script.

    Option 1: Install standalone package

    Use pymanager to target a specific directory, then install requirements via pip into that target.

    Option 2: Build self-contained package

    Use the scripts/build_selfcontained.py script to create a self-contained environment.

    # Option 1: Standalone
    pymanager install --target=testapp
    testapp/python.exe -m pip install -r test_requirements.txt
    
    # Option 2: Self-contained
    py scripts/build_selfcontained.py --target=testapp
    # install win32more
    > pymanager install --target=testapp
    # install win32more
    > testapp/python.exe -m pip install -r test_requirements.txt
    
    # Create self-contained package
    > py scripts/build_selfcontained.py --target=testapp
  6. Common properties for ICanvasEffect

    main

    Most Win2D effects implement the ICanvasEffect interface, providing several shared properties and methods for managing effect behavior and resource requirements:

    Properties:

    • CacheOutput: Boolean indicating if the effect output should be cached.
    • BufferPrecision: A reference to the CanvasBufferPrecision used for rendering.
    • Name: A unique string identifier for the effect.

    Methods:

    • InvalidateSourceRectangle(...): Invalidates a specific portion of the source.
    • GetInvalidRectangles(...): Returns an array of rectangles that are invalid.
    • GetRequiredSourceRectangle(...): Calculates the required source rectangle for a given output rectangle.
    • GetRequiredSourceRectangles(...): Calculates multiple required source rectangles for multiple effects/indices.
  7. Handle printing and preview events using CanvasPrintDeferral

    main

    When handling Preview or Print events in Win2D, the operations are often asynchronous. To prevent the system from proceeding before your drawing is complete, you must use a CanvasPrintDeferral.

    1. In your event handler, call GetDeferral() on the event arguments (CanvasPrintEventArgs or CanvasPreviewEventArgs).
    2. Perform your drawing operations using the provided DrawingSession.
    3. Call .Complete() on the deferral object to signal that drawing is finished.

    In Python, if the deferral object supports the context manager protocol, you can use with args.GetDeferral() as deferral: to ensure Complete() is called automatically.

    def on_print(sender, args):
        # Using the deferral to manage asynchronous drawing
        deferral = args.GetDeferral()
        try:
            session = args.CreateDrawingSession()
            # ... drawing logic ...
        finally:
            deferral.Complete()
  8. Build custom paths with ICanvasPathBuilder

    main

    Use ICanvasPathBuilder to construct complex, custom geometries step-by-step. You typically create a builder via ICanvasPathBuilderFactory.Create(resource_creator).

    Workflow:

    1. Begin a Figure: Use BeginFigure(startPoint) or BeginFigureAtCoords(x, y) to start a new sub-path. You can also use BeginFigureWithFigureFill to specify a fill mode immediately.
    2. Add Segments:
      • AddLine(endPoint) or AddLineWithCoords(x, y)
      • AddArcToPoint(...) (for elliptical arcs)
      • AddArcAroundEllipse(...)
      • AddCubicBezier(cp1, cp2, endPoint)
      • AddQuadraticBezier(cp, endPoint)
      • AddGeometry(geometry) (to embed existing shapes)
    3. End the Figure: Call EndFigure(figureLoop) to close or leave the figure open.
    4. Create Geometry: Pass the builder to ICanvasGeometryStatics.CreatePath(pathBuilder) to finalize the CanvasGeometry.
    # Conceptual workflow
    builder = ICanvasPathBuilderFactory.Create(resource_creator)
    builder.BeginFigure(start_point)
    builder.AddLine(end_point)
    builder.EndFigure(figure_loop)
    
    geometry = ICanvasGeometryStatics.CreatePath(builder)
  9. Verify package identity in Python

    main

    Once your application is running as a packaged app, you can verify its identity using GetCurrentPackageFullName from the win32more.Windows.Win32.Storage.Packaging.Appx module.

    from win32more import Char, UInt32
    from win32more.Windows.Win32.Storage.Packaging.Appx import GetCurrentPackageFullName
    
    # Prepare buffers
    buf = (Char * 1024)()
    length = UInt32(1024)
    
    # Call API
    GetCurrentPackageFullName(length, buf)
    print(buf.value)
    from win32more import Char, UInt32
    from win32more.Windows.Win32.Storage.Packaging.Appx import GetCurrentPackageFullName
    
    buf = (Char * 1024)()
    length = UInt32(1024)
    GetCurrentPackageFullName(length, buf)
    0
    >>> buf.value
    'Win32more.TestApp_1.0.0.0_x64__x22gc0rg6bp3w'
  10. Load UI from XAML files

    main

    You can define your UI in a .xaml file and load it into a window using XamlReader.Load(). This allows for a clean separation of UI design and logic.

    Example Python code:

    from win32more.winui3 import XamlApplication
    from win32more.Microsoft.UI.Xaml import Window
    from win32more.Microsoft.UI.Xaml.Media import MicaBackdrop
    from win32more.Microsoft.UI.Xaml.Markup import XamlReader
    
    class App(XamlApplication):
        def OnLaunched(self, args):
            win = Window()
            win.SystemBackdrop = MicaBackbackdrop()
            with open("page.xaml", "r", encoding='utf-8') as file:
                win.Content = XamlReader.Load(file.read())
            win.Activate()
    
    XamlApplication.Start(App)

    Example page.xaml:

    <Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <NavigationView IsBackButtonVisible="Collapsed">
            <NavigationView.MenuItems>
                <NavigationViewItem Content="Home" Icon="Home" />
            </NavigationView.MenuItems>
            <Frame>
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <TextBlock Text="WinUI 3 with Python!" FontSize="40" Padding="10" HorizontalAlignment="Center" />
                    <HyperlinkButton Content="GitHub repository" NavigateUri="https://github.com/ynkdir/py-win32more" HorizontalAlignment="Center" />
                </StackPanel>
            </Frame>
        </NavigationView>
    </Page>
    from win32more.winui3 import XamlApplication
    from win32more.Microsoft.UI.Xaml import Window
    from win32more.Microsoft.UI.Xaml.Media import MicaBackdrop
    from win32more.Microsoft.UI.Xaml.Markup import XamlReader
    
    class App(XamlApplication):
        def OnLaunched(self, args):
            win = Window()
            win.SystemBackdrop = MicaBackdrop()
            with open("page.xaml", "r", encoding='utf-8') as file:
                win.Content = XamlReader.Load(file.read())
            win.Activate()
    
    XamlApplication.Start(App)
  11. Add UI elements and handle click events

    main

    To add elements like a Button to a window, import the control from its corresponding namespace (e.g., Microsoft.UI.Xaml.Controls) and assign it to win.Content.

    To handle events, use the .add_<EventName> method on the control instance. For a button click, use .add_Click(callback_method).

    Example:

    from win32more.Microsoft.UI.Xaml import Window
    from win32more.Microsoft.UI.Xaml.Controls import Button
    from win32more.winui3 import XamlApplication
    
    class App(XamlApplication):
        def OnLaunched(self, args):
            win = Window()
            
            btn = Button()
            btn.Content = "Hello World"
            btn.add_Click(self.ButtonClick) # Link event to method
            
            win.Content = btn
            win.Activate()
        
        def ButtonClick(self, sender, args):
            print("Hello World")
    
    XamlApplication.Start(App)
    from win32more.Microsoft.UI.Xaml import Window
    from win32more.Microsoft.UI.Xaml.Controls import Button
    from win32more.winui3 import XamlApplication
    
    class App(XamlApplication):
        def OnLaunched(self, args):
            win = Window()
            
            btn = Button()
            btn.Content = "Hello World"
            btn.add_Click(self.ButtonClick)
            
            win.Content = btn
            win.Activate()
        
        def ButtonClick(self, sender, args):
            print("Hello World")
    
    XamlApplication.Start(App)
  12. Create AppxManifest.xml for packaging

    main

    The AppxManifest.xml defines the identity, capabilities, and entry points of your packaged application. Key elements include:

    • <Identity>: Defines the Name, Version, and Publisher.
    • <Capabilities>: Grants permissions like runFullTrust or systemAIModels.
    • <Application>: Specifies the Executable (e.g., python.exe), the EntryPoint (e.g., Windows.FullTrustApplication), and the uap10:RuntimeBehavior (e.g., packagedClassicApp).
    • <Extensions>: Can define appExecutionAlias to allow running the app via a custom alias like testapp.exe.

    Note: If you are creating a self-contained package, remove the <PackageDependency> entry from the <Dependencies> section.

    <?xml version="1.0" encoding="utf-8"?>
    <Package
        xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
        xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
        xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
        xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
        xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
        xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
        xmlns:systemai="http://schemas.microsoft.com/appx/manifest/systemai/windows10"
        IgnorableNamespaces="uap rescap systemai desktop4">
    
        <Identity Name="Win32more.TestApp" Version="1.0.0.0" Publisher="CN=CommonName, O=Organization, L=City, S=State, C=Country" ProcessorArchitecture="x64" />
    
        <Properties>
            <DisplayName>Win32more.TestApp</DisplayName>
            <PublisherDisplayName>Win32more</PublisherDisplayName>
            <Description>TestApp</Description>
            <Logo>logo.png</Logo>
        </Properties>
    
        <Resources>
            <Resource Language="en-us" />
        </Resources>
    
        <Dependencies>
            <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26226.0" />
            <!-- Specify your dependency.  Remove this line for self-contained package. -->
            <PackageDependency Name="Microsoft.WindowsAppRuntime.1.8" MinVersion="8000.0.0.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" />
        </Dependencies>
    
        <Capabilities>
            <rescap:Capability Name="runFullTrust"/>
            <systemai:Capability Name="systemAIModels"/>
        </Capabilities>
    
        <Applications>
            <Application
                    Id="TestApp"
                    Executable="python.exe"
                    EntryPoint="Windows.FullTrustApplication"
                    uap10:RuntimeBehavior="packagedClassicApp"
                    uap10:TrustLevel="mediumIL">
                <uap:VisualElements
                    DisplayName="TestApp"
                    Description="TestApp"
                    BackgroundColor="#464646"
                    Square150x150Logo="logo.png"
                    Square44x44Logo="logo.png"
                    />
                <Extensions>
                    <uap5:Extension Category="windows.appExecutionAlias">
                        <uap5:AppExecutionAlias desktop4:Subsystem="windows">
                            <uap5:ExecutionAlias Alias="testapp.exe" />
                        </uap5:AppExecutionAlias>
                    </uap5:Extension>
                </Extensions>
            </Application>
        </Applications>
    
    </Package>