Build your first native Windows application.
Start with an empty folder and finish with a real, resizable HWND window. Every command and file you need is on this page.
Know what the tools do
- Visual Studio supplies the MSVC C++ compiler, Windows SDK, debugger, and CMake.
- Git lets CMake download mwfl and its pinned dependencies.
- CMake reads
CMakeLists.txtand creates a Visual Studio build.
You do not need to create a .sln file, configure include directories, or download WIL manually.
Install Visual Studio and Git
- Install Visual Studio 2026 Community or Visual Studio 2022 Community.
- In Visual Studio Installer, select Desktop development with C++.
- Under Individual components, confirm these items:
- MSVC x64/x86 build tools
- C++ CMake tools for Windows
- Windows 11 SDK or a recent Windows 10 SDK
- Install Git for Windows if
gitis not already available. - From the Start menu, open Developer PowerShell for VS 2026. For VS 2022, open its corresponding Developer PowerShell.
git --version
cmake --version
cl
Success means all three commands are found. cl prints a compiler version and then reports that no source files were supplied; that final message is expected.
Create an empty project folder
New-Item -ItemType Directory -Path "$HOME\source\mwfl-hello"
Set-Location "$HOME\source\mwfl-hello"
New-Item -ItemType File CMakeLists.txt, main.cpp, app.manifest
Open this folder in your editor. Its final shape is:
mwfl-hello/
├── CMakeLists.txt
├── main.cpp
└── app.manifest
1. CMakeLists.txt
This downloads a tested release, creates a Windows GUI executable, enables C++20, and links mwfl.
cmake_minimum_required(VERSION 3.21)
project(mwfl_hello LANGUAGES CXX)
include(FetchContent)
FetchContent_Declare(mwfl
GIT_REPOSITORY https://github.com/mwfl/mwfl.git
GIT_TAG v0.1.0
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(mwfl)
add_executable(mwfl_hello WIN32 main.cpp app.manifest)
set_property(SOURCE app.manifest PROPERTY VS_TOOL_OVERRIDE "Manifest")
target_compile_features(mwfl_hello PRIVATE cxx_std_20)
target_compile_options(mwfl_hello PRIVATE /W4 /permissive- /EHsc /utf-8)
target_link_libraries(mwfl_hello PRIVATE mwfl::app)
2. main.cpp
#include <mwfl/mwfl.h>
using mwfl::operator""_dip;
class MainWindow final : public mwfl::WindowBase {
public:
void BuildUI() override {
SetTitle(L"My first mwfl application");
mwfl::ControlHost ui{*this};
ui.Add(message_, L"Hello from a native HWND window.");
ui.Add(close_, L"Close");
SetLayout(mwfl::Column()
.Margin(24_dip)
.Gap(12_dip)
.Add(message_, mwfl::Stretch())
.Add(close_, mwfl::Fixed(38_dip)));
}
mwfl::EventResult OnCommand(
const mwfl::CommandEvent& event) override {
if (event.IsClicked(close_)) {
Close();
return mwfl::EventResult::Handled();
}
return mwfl::EventResult::Propagate();
}
private:
mwfl::Label message_;
mwfl::Button close_;
};
int WINAPI wWinMain(
HINSTANCE instance, HINSTANCE, PWSTR, int show) {
return mwfl::RunApplication<MainWindow>(instance, show);
}
3. app.manifest
The manifest enables current Common Controls and Per-Monitor-V2 DPI behavior.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="mwfl.hello" processorArchitecture="*"
version="1.0.0.0" type="win32" />
<dependency><dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls"
version="6.0.0.0" processorArchitecture="*"
publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly></dependency>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
</windowsSettings>
</application>
</assembly>
Configure the project
Run one of these commands from the folder containing the three files.
cmake -S . -B build -G "Visual Studio 18 2026" -A x64
cmake -S . -B build -G "Visual Studio 17 2022" -A x64
The first configure needs internet access and may take a minute while Git downloads mwfl and WIL. Success ends with:
-- Configuring done
-- Generating done
-- Build files have been written to: .../mwfl-hello/build
build-vs2022.Build and run
cmake --build build --config Debug --parallel 2
& .\build\Debug\mwfl_hello.exe
A resizable native Windows window should open with a label and a Close button. Resize it to see the retained layout update the real child controls.
If the build succeeds but the executable path differs, locate it with:
Get-ChildItem build -Recurse -Filter mwfl_hello.exe
Run in Visual Studio
- Choose File → Open → Folder and select
mwfl-hello. - Wait for CMake generation to finish.
- Select
mwfl_hello.exeas the startup item. - Press F5 to debug or Ctrl+F5 to run without the debugger.
Make and verify a change
Change the title or label in main.cpp, save the file, then rebuild:
cmake --build build --config Debug --parallel 2
& .\build\Debug\mwfl_hello.exe
You normally configure once and rebuild after source edits. Run the configure command again only after changing CMake options or dependency settings.
Troubleshooting
“Could not find any instance of Visual Studio”
Install the Desktop development with C++ workload, use the generator matching your installed Visual Studio version, and reopen Developer PowerShell.
Git clone or FetchContent fails
Confirm git --version works and that GitHub is reachable. Corporate proxies may require Git proxy configuration. Retry the configure command after connectivity is restored.
Generator does not match the previous generator
You reused a build directory with another Visual Studio version. Create a new directory, for example build-vs2022 or build-vs2026.
Linker cannot find wWinMain
Keep WIN32 in add_executable and use the exact wWinMain signature shown above.
The window is blurry or controls look old
Ensure app.manifest is listed in the executable sources and retains the Common Controls and DPI declarations.
x86 configuration is rejected
mwfl intentionally supports only x64 and ARM64. Use -A x64 for a normal PC.
Start over safely
Close Visual Studio, remove only the project’s generated build directory, and repeat Configure and Build. Do not delete your three source files.
Next steps
- Build the complete Notepad reference application, including safe files, commands, GUI tests, and packaging.
- Browse every component with screenshots and source.
- Copy a maintained starter template.
- Read the build reference for installed packages, ARM64, VS Code, repository development, and offline dependencies.
- Build the persistent Settings application step by step, including Apply/OK/Cancel, validation, task-dialog feedback, and automated tests.
- Build the Explorer-style application step by step, including stable navigation, virtual data, split panes, commands, and GUI tests.
- Explore all runnable examples.