Crate winsafe

source ·
Expand description

Windows API and GUI in safe, idiomatic Rust.

CrateGitHubDocs (stable)Docs (master branch)Examples

WinSafe has:

  • low-level Win32 API constants, functions and structs;
  • high-level structs to build native Win32 GUI applications.

§Usage

Add the dependency in your Cargo.toml:

[dependencies]
winsafe = { version = "0.0.22", features = [] }

Then you must enable the Cargo features you want to be included – these modules are named after native Windows DLL and library names, mostly.

The following Cargo features are available so far:

FeatureDescription
advapiAdvapi32.dll and Ktmw32.dll, advanced kernel functions
comctlComCtl32.dll, the Common Controls
dshowDirectShow
dwmDesktop Window Manager
dxgiDirectX Graphics Infrastructure
gdiGdi32.dll, the Windows GDI
guiThe WinSafe high-level GUI abstractions
kernelKernel32.dll, basic kernel functions
mfMedia Foundation
oleBasic OLE/COM support
oleautOLE Automation
raw-dylibEnables raw-dylib linking
shellShell32.dll, Shlwapi.dll, and Userenv.dll, the COM-based Windows Shell
taskschdTask Scheduler
userUser32.dll and ComDlg32.dll, the basic Windows GUI support
uxthemeUxTheme.dll, extended window theming
versionVersion.dll, to manipulate *.exe version info

If you’re looking for a comprehensive Win32 coverage, take a look at winapi or windows crates, which are unsafe, but have everything.

§The GUI API

WinSafe features idiomatic bindings for the Win32 API, but on top of that, it features a set of high-level GUI structs, which scaffolds the boilerplate needed to build native Win32 GUI applications, event-oriented. Unless you’re doing something really specific, these high-level wrappers are highly recommended – you’ll usually start with the WindowMain.

One of the greatest strenghts of the GUI API is supporting the use of resource files, which can be created with a WYSIWYG resource editor.

GUI structs can be found in module gui.

§Native function calls

The best way to understand the idea behind WinSafe bindings is comparing them to the correspondent C code.

For example, take the following C code:

HWND hwnd = GetDesktopWindow();
SetFocus(hwnd);

This is equivalent to:

use winsafe::{prelude::*, HWND};

let hwnd = HWND::GetDesktopWindow();
hwnd.SetFocus();

Note how GetDesktopWindow is a static method of HWND, and SetFocus is an instance method called directly upon hwnd. All native handles (HWND, HDC, HINSTANCE, etc.) are structs, thus:

  • native Win32 functions that return a handle are static methods in WinSafe;
  • native Win32 functions whose first parameter is a handle are instance methods.

Now this C code:

PostQuitMessage(0);

Is equivalent to:

use winsafe::PostQuitMessage;

PostQuitMessage(0);

Since PostQuitMessage is a free function, it’s simply at the root of the crate.

Also note that some functions which require a cleanup routine – like BeginPaint, for example – will return the resource wrapped in a guard, which will perform the cleanup automatically. You’ll never have to manually call EndPaint.

Sending messages are a special case, see the msg module.

§Native constants

All native Win32 constants can be found in the co module. They’re all typed, what means that different constant types cannot be mixed (unless you explicitly say so).

Technically, each constant type is simply a newtype with a couple implementations, including those allowing bitflag operations. Also, all constant values can be converted to its underlying integer type.

The name of the constant type is often its prefix. For example, constants of MessageBox function, like MB_OKCANCEL, belong to a type called MB.

For example, take the following C code:

let hwnd = GetDesktopWindow();
MessageBox(hwnd, "Hello, world", "My hello", MB_OKCANCEL | MB_ICONINFORMATION);

This is equivalent to:

use winsafe::{prelude::*, co::MB, HWND};

let hwnd = HWND::GetDesktopWindow();
hwnd.MessageBox("Hello, world", "Title", MB::OKCANCEL | MB::ICONINFORMATION)?;

The method MessageBox, like most functions that can return errors, will return SysResult, which can contain an ERROR constant.

§Native structs

WinSafe implements native Win32 structs in a very restricted way. First off, fields which control the size of the struct – often named cbSize – are private and automatically set when the struct is instantiated.

Pointer fields are also private, and they can be set and retrieved only through getter and setter methods. In particular, when setting a string pointer field, you need to pass a reference to a WString buffer, which will keep the actual string contents.

For example, the following C code:

WNDCLASSEX wcx = {0};
wcx.cbSize = sizeof(WNDCLASSEX);
wcx.lpszClassName = "MY_WINDOW";

if (RegisterClassEx(&wcx) == 0) {
    DWORD err = GetLastError();
    // handle error...
}

Is equivalent to:

use winsafe::{RegisterClassEx, WNDCLASSEX, WString};

let mut wcx = WNDCLASSEX::default();

let mut buf = WString::from_str("MY_WINDOW");
wcx.set_lpszClassName(Some(&mut buf));

if let Err(err) = RegisterClassEx(&wcx) {
    // handle error...
}

Note how you don’t need to call GetLastError to retrieve the error code: it’s returned by the method itself in the SysResult.

§Text encoding

Windows natively uses Unicode UTF-16.

WinSafe uses Unicode UTF-16 internally but exposes idiomatic UTF-8, performing conversions automatically when needed, so you don’t have to worry about OsString or any low-level conversion.

However, there are cases where a string conversion is still needed, like when dealing with native Win32 structs. In such cases, you can use the WString struct, which is also capable of working as a buffer to receive text from Win32 calls.

§Errors and result aliases

WinSafe declares a few Result aliases which are returned by its functions and methods:

AliasErrorUsed for
SysResultERRORStandard system errors.
HrResultHRESULTCOM errors.
AnyResultBox<dyn Error + Send + Sync>Holding different error types. All other Result aliases can be converted into it.

§Utilities

Beyond the GUI API, WinSafe features a few high-level abstractions to deal with some particularly complex Win32 topics. Unless you need something specific, prefer using these over the raw, native calls:

UtilityUsed for
EncodingString encodings.
FileFile read/write and other operations.
FileMappedMemory-mapped file operations.
pathFile path operations.
WStringManaging native wide strings.

Modules§

  • cokernel
    Native constants.
  • guardkernel
    RAII implementation for various resources, which automatically perform cleanup routines when the object goes out of scope.
  • guigui
    High-level GUI abstractions for user windows and native controls. They can be created programmatically or by loading resources from a .res file. These files can be created with a WYSIWYG resource editor.
  • msguser
    Parameters of window messages.
  • pathkernel
    File path utilities.
  • preludekernel
    The WinSafe prelude.

Macros§

  • Generates sequential u16 constants starting from the given value.

Structs§

Enums§

Functions§

Type Aliases§