win32/embedded_manifest Windows

Overview

Embedded manifest example

Windows executables can contain manifests. Manifests are metadata can control various aspects before and during program execution. The most common use cases are:

  • UAC awareness (for privilege escalation)
  • DPI awareness (for correctly rendering at >96 dpi)
  • Enabling visual styles (Common Controls v6)

This example uses the manifest to enable visual styles, which will affect the appearance of a button.

Embedding manifests with Odin

Manifests are regular embedded resources (such as images or localized strings), so they can be embedded with a .rc script. They use resource type RT_MANIFEST (numeric value 24), and the main application manifest is expected to have resource ID 1.

See the contents of resource.rc and compile with:

odin build . -resource:resource.rc

Alternatively, a manifest can be embedded into an existing binary with the mt.exe tool, which is part of the Windows SDK:

mt.exe -manifest app.manifest -outputresource:embedded_manifest.exe;1

Troubleshooting

If you are seeing:

error RC1015: cannot open include file 'winuser.h'

Your build environment is not set up properly for rc.exe, which is the component that compiles the resource.rc file. The easiest fix is to launch the developer command prompt for Visual Studio, and build from there.

Alternatively, you must manually ensure that your local Windows SDK's appropriate Include directory is added to your %INCLUDE% envrionment variable.

Code

main.odin ¶
71 linesSource

1package manifest_example
2
3import runtime "base:runtime"
4import win "core:sys/windows"
5
6main :: proc() {
7	instance := win.HINSTANCE(win.GetModuleHandleW(nil))
8	assert(instance != nil, "Failed to fetch current instance")
9	CLASS_NAME :: "ManifestExampleWindow"
10
11	startup_info : win.STARTUPINFOW
12	win.GetStartupInfoW(&startup_info)
13	nCmdShow := (startup_info.dwFlags & win.STARTF_USESHOWWINDOW) != 0 ? cast(win.c_int)startup_info.wShowWindow : win.SW_SHOWDEFAULT
14
15	cls := win.WNDCLASSW {
16		lpfnWndProc = wndproc,
17		lpszClassName = CLASS_NAME,
18		hInstance = instance,
19		hCursor = win.LoadCursorA(nil, win.IDC_ARROW),
20		hbrBackground = win.GetSysColorBrush(win.COLOR_3DFACE),
21	}
22
23	class := win.RegisterClassW(&cls)
24	assert(class != 0, "Class creation failed")
25
26	hwnd := win.CreateWindowW(CLASS_NAME,
27		"Manifest example",
28		win.WS_OVERLAPPEDWINDOW,
29		win.CW_USEDEFAULT, 0, 800, 600,
30		nil, nil, instance, nil)
31
32	assert(hwnd != nil, "Window creation failed")
33
34	win.ShowWindow(hwnd, nCmdShow)
35	win.UpdateWindow(hwnd)
36
37	msg: win.MSG
38
39	for	win.GetMessageW(&msg, nil, 0, 0) > 0 {
40		win.TranslateMessage(&msg)
41		win.DispatchMessageW(&msg)
42	}
43}
44
45wndproc :: proc "system"(hwnd: win.HWND, msg: win.UINT, wparam: win.WPARAM, lparam: win.LPARAM) -> win.LRESULT {
46	switch msg {
47	case win.WM_CREATE:
48		context = runtime.default_context()
49		// Create a button to demonstrate the visual effect of Common Controls v6.
50		button := win.CreateWindowExW(0, "BUTTON", "",
51			win.WS_CHILD | win.WS_VISIBLE,
52			10, 10, 150, 30,
53			hwnd, nil, nil, nil)
54		assert(button != nil, "Button creation failed")
55
56		// In addition to the change in visual appearance of the button we just created,
57		// we *attempt* to detect programmatically whether we've successfully linked to Common Controls v6.
58		// However, this is not an intended use case, so it may or may not work reliably on your system.
59		// Do NOT use this in production code.
60		if win.GetWindowTheme(button) != nil {
61			// Common Controls v6 is probably linked successfully.
62			win.SetWindowTextW(button, "Modern button")
63		} else {
64			// Common Controls v6 is probably not linked successfully.
65			win.SetWindowTextW(button, "Dated button")
66		}
67	case win.WM_DESTROY:
68		win.PostQuitMessage(0)
69	}
70	return win.DefWindowProcW(hwnd, msg, wparam, lparam)
71}

Other Files

app.manifest ¶
14 linesSource

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="*"
        publicKeyToken="6595b64144ccf1df"
        language="*"/>
    </dependentAssembly>
  </dependency>
</assembly>

resource.rc ¶
3 linesSource

#include <winuser.h>

1 RT_MANIFEST "app.manifest"

Declarations Used 37