### Window Creation and Display Example (Rust)
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Example of creating a window using CreateWindowExW and displaying it with ShowWindow. Panics if window creation fails.
```rust
fn main() {
// first register the class, as before
let sample_window_name_wn = wide_null("Sample Window Name");
let hwnd = unsafe {
CreateWindowExW(
0,
sample_window_class_wn.as_ptr(),
sample_window_name_wn.as_ptr(),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
core::ptr::null_mut(),
core::ptr::null_mut(),
hInstance,
core::ptr::null_mut(),
)
};
if hwnd.is_null() {
panic!("Failed to create a window.");
}
}
```
```rust
let _previously_visible = unsafe { ShowWindow(hwnd, SW_SHOW) };
```
--------------------------------
### Example Usage of Pixel Format Functions
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Demonstrates the sequence of calls to get a device context, choose a pixel format, set it, and then release the device context. This is a typical workflow for initializing OpenGL rendering.
```rust
let fake_hdc = unsafe { get_dc(fake_hwnd) }.unwrap();
let pf_index = unsafe { choose_pixel_format(fake_hdc, &pfd) }.unwrap();
unsafe { set_pixel_format(fake_hdc, pf_index, &pfd) }.unwrap();
assert!(unsafe { release_dc(fake_hwnd, fake_hdc) });
unsafe { destroy_window(fake_hwnd) }.unwrap()
```
--------------------------------
### Window Procedure Painting Example
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
An example demonstrating the usage of begin_paint, fill_rect_with_sys_color, and end_paint within a window procedure's message handling.
```rust
// in `window_procedure`
match begin_paint(hwnd) {
Ok((hdc, ps)) => {
let _ = fill_rect_with_sys_color(hdc, &ps.rcPaint, SysColor::Window);
end_paint(hwnd, &ps);
}
Err(e) => {
println!("Couldn't begin painting: {}", e)
}
}
```
--------------------------------
### JavaScript Setup for WebGL
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/web_crate/index.html
Initializes the WebGL context and handles canvas setup. This function is called from WebAssembly.
```javascript
var gl;
var canvas;
var wasm_memory;
var js_objects = [null];
const decoder = new TextDecoder();
function setupCanvas() {
console.log("Setting up the canvas.");
let canvas = document.getElementById("my_canvas");
gl = canvas.getContext("webgl");
if (!gl) {
console.log("Failed to get a WebGL context for the canvas!");
return;
}
}
```
--------------------------------
### Install devserver for local hosting
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Install the devserver tool using Cargo to serve local files, which is necessary for testing WebAssembly applications in a browser.
```bash
cargo install devserver
```
--------------------------------
### Rust WebGL Triangle Setup
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Initializes WebGL, sets up vertex and index buffers, compiles shaders, links the program, and draws a triangle. This is the main entry point for rendering.
```rust
#[no_mangle]
pub extern "C" fn start() {
unsafe {
js::setupCanvas();
let vertex_data = [-0.2_f32, 0.5, 0.0, -0.5, -0.4, 0.0, 0.5, -0.1, 0.0];
let vertex_buffer = js::createBuffer();
js::bindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
js::bufferDataF32(
GL_ARRAY_BUFFER,
vertex_data.as_ptr(),
vertex_data.len(),
GL_STATIC_DRAW,
);
let index_data = [0_u16, 1, 2];
let index_buffer = js::createBuffer();
js::bindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
js::bufferDataU16(
GL_ELEMENT_ARRAY_BUFFER,
index_data.as_ptr(),
index_data.len(),
GL_STATIC_DRAW,
);
let vertex_shader_text = "
attribute vec3 vertex_position;
void main(void) {
gl_Position = vec4(vertex_position, 1.0);
}";
let vertex_shader = js::createShader(GL_VERTEX_SHADER);
js::shaderSource(
vertex_shader,
vertex_shader_text.as_bytes().as_ptr(),
vertex_shader_text.len(),
);
js::compileShader(vertex_shader);
let fragment_shader_text = "
void main() {
gl_FragColor = vec4(1.0, 0.5, 0.313, 1.0);
}";
let fragment_shader = js::createShader(GL_FRAGMENT_SHADER);
js::shaderSource(
fragment_shader,
fragment_shader_text.as_bytes().as_ptr(),
fragment_shader_text.len(),
);
js::compileShader(fragment_shader);
let shader_program = js::createProgram();
js::attachShader(shader_program, vertex_shader);
js::attachShader(shader_program, fragment_shader);
js::linkProgram(shader_program);
js::useProgram(shader_program);
let name = "vertex_position";
let attrib_location = js::getAttribLocation(
shader_program,
name.as_bytes().as_ptr(),
name.len(),
);
assert!(attrib_location != GLuint::MAX);
js::enableVertexAttribArray(attrib_location);
js::vertexAttribPointer(attrib_location, 3, GL_FLOAT, false, 0, 0);
js::clearColor(0.37, 0.31, 0.86, 1.0);
js::clear(GL_COLOR_BUFFER_BIT);
js::drawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
}
}
```
--------------------------------
### Registering a Window Class with Error Handling
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Example of registering a window class and checking for errors using `RegisterClassW` and `GetLastError`. Panics if registration fails.
```rust
fn main() {
let hInstance = unsafe { GetModuleHandleW(core::ptr::null()) };
let sample_window_class_wn = wide_null("Sample Window Class");
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(dummy_window_procedure);
wc.hInstance = hInstance;
wc.lpszClassName = sample_window_class_wn.as_ptr();
let atom = unsafe { RegisterClassW(&wc) };
if atom == 0 {
let last_error = unsafe { GetLastError() };
panic!("Could not register the window class, error code: {}", last_error);
}
}
```
--------------------------------
### Registering a Window Class
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Example of registering a window class using `RegisterClassW` in Rust. Ensure `GetModuleHandleW` and `wide_null` are defined elsewhere.
```rust
fn main() {
let hInstance = unsafe { GetModuleHandleW(core::ptr::null()) };
let sample_window_class_wn = wide_null("Sample Window Class");
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(dummy_window_procedure);
wc.hInstance = hInstance;
wc.lpszClassName = sample_window_class_wn.as_ptr();
unsafe { RegisterClassW(&wc) };
}
```
--------------------------------
### JavaScript Canvas Setup Function
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Initializes the WebGL rendering context for a given canvas element.
```javascript
function setupCanvas() {
console.log("Setting up the canvas.");
let canvas = document.getElementById("my_canvas");
gl = canvas.getContext("webgl");
if (!gl) {
console.log("Failed to get a WebGL context for the canvas!");
return;
}
}
```
--------------------------------
### PIXELFORMATDESCRIPTOR Initialization (C)
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Example of how to initialize a PIXELFORMATDESCRIPTOR struct in C for Win32 OpenGL.
```c
PIXELFORMATDESCRIPTOR pfd =
{
ssizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, // Number of bits for the depthbuffer
8, // Number of bits for the stencilbuffer
0, // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
```
--------------------------------
### HTML Canvas Setup
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Basic HTML structure including a canvas element and a script tag for JavaScript initialization.
```html
```
--------------------------------
### Setup Canvas and Clear to Blue in JavaScript
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
This JavaScript code sets up the WebGL context for a canvas and provides a function to clear the canvas to a specific blue color. It's designed to be imported by WebAssembly.
```html
```
--------------------------------
### Export Wasm function with C ABI
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Define a Rust function 'start' that is exported with the C ABI and has name mangling disabled. This function will be the entry point called by JavaScript when the WebAssembly module is loaded.
```rust
// lib.rs
#[no_mangle]
pub extern "C" fn start() {
// nothing yet!
}
```
--------------------------------
### Rust Cargo Project Initialization and Run
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Demonstrates initializing a new Rust binary project using Cargo and running the default 'Hello, world!' application.
```bash
Microsoft Windows [Version 10.0.19041.685]
(c) 2020 Microsoft Corporation. All rights reserved.
D:\dev\triangle-from-scratch>cargo init --bin
Created binary (application) package
D:\dev\triangle-from-scratch>cargo run
Compiling triangle-from-scratch v0.1.0 (D:\dev\triangle-from-scratch)
Finished dev [unoptimized + debuginfo] target(s) in 0.65s
Running `target\debug\triangle-from-scratch.exe`
Hello, world!
```
--------------------------------
### Window Creation and HDC Initialization
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Demonstrates creating a window and obtaining its device context (HDC) during initialization. The HDC is stored in the WindowData structure.
```rust
// fn main
let lparam: *mut WindowData = Box::leak(Box::new(WindowData::default()));
let hwnd = unsafe {
create_app_window(
sample_window_class,
"Sample Window Name",
None,
[800, 600],
lparam.cast(),
)
}
.unwrap();
let hdc = unsafe { get_dc(hwnd) }.unwrap();
unsafe { (*lparam).hdc = hdc };
```
--------------------------------
### Add wasm32-unknown-unknown target
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Install the WebAssembly target for the Rust compiler. This is a prerequisite for compiling Rust code to WebAssembly.
```bash
rustup target add wasm32-unknown-unknown
```
--------------------------------
### Function Signatures Returning Win32Error
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
Example function signatures that return a Result with a custom Win32Error type. These functions interact with the Win32 API.
```rust
pub fn load_predefined_cursor(cursor: IDCursor) -> Result {
// ...
}
```
```rust
pub unsafe fn register_class(
window_class: &WNDCLASSW,
) -> Result {
// ...
}
```
--------------------------------
### Loading opengl32.dll during Window Initialization
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Demonstrates loading the `opengl32.dll` library and assigning its module handle to the `WindowData` struct after an OpenGL context has been created. This ensures the OpenGL library is available for use.
```rust
unsafe { wgl_make_current(hdc, hglrc) }.unwrap();
unsafe { (*lparam).hglrc = hglrc };
let opengl32 = load_library("opengl32.dll").unwrap();
unsafe { (*lparam).opengl32 = opengl32 };
```
--------------------------------
### Create and Register Fake Window Class
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Sets up and registers a 'Fake Window Class' with specific properties like CS_OWNDC style and a default window procedure. This is a workaround for issues preventing window display.
```rust
fn main() {
// fake window stuff
let fake_window_class = "Fake Window Class";
let fake_window_class_wn = wide_null(fake_window_class);
let mut fake_wc = WNDCLASSW::default();
fake_wc.style = CS_OWNDC;
fake_wc.lpfnWndProc = Some(DefWindowProcW);
fake_wc.hInstance = get_process_handle();
fake_wc.lpszClassName = fake_window_class_wn.as_ptr();
let _atom = unsafe { register_class(&fake_wc) }.unwrap();
let pfd = // ...
let fake_hwnd = unsafe {
create_app_window(
fake_window_class,
"Fake Window",
None,
[1, 1],
null_mut(),
)
}
.unwrap();
```
--------------------------------
### WebGL Import Object for Wasm
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
Defines the functions that WebAssembly will call to interact with the WebGL API. This includes setup, buffer manipulation, shader operations, and drawing commands.
```javascript
var importObject = {
env: {
setupCanvas: setupCanvas,
attachShader: function (program, shader) {
gl.attachShader(js_objects[program], js_objects[shader]);
},
bindBuffer: function (target, id) {
gl.bindBuffer(target, js_objects[id]);
},
bufferDataF32: function (target, data_ptr, data_length, usage) {
const data = new Float32Array(wasm_memory.buffer, data_ptr, data_length);
gl.bufferData(target, data, usage);
},
bufferDataU16: function (target, data_ptr, data_length, usage) {
const data = new Uint16Array(wasm_memory.buffer, data_ptr, data_length);
gl.bufferData(target, data, usage);
},
clear: function (mask) {
gl.clear(mask)
},
clearColor: function (r, g, b, a) {
gl.clearColor(r, g, b, a);
},
compileShader: function (shader) {
gl.compileShader(js_objects[shader]);
},
createBuffer: function () {
return js_objects.push(gl.createBuffer()) - 1;
},
createProgram: function () {
return js_objects.push(gl.createProgram()) - 1;
},
createShader: function (shader_type) {
return js_objects.push(gl.createShader(shader_type)) - 1;
},
drawElements: function (mode, count, type, offset) {
gl.drawElements(mode, count, type, offset);
},
enableVertexAttribArray: function (index) {
gl.enableVertexAttribArray(index)
},
getAttribLocation: function (program, pointer, length) {
const string_data = new Uint8Array(wasm_memory.buffer, pointer, length);
const string = decoder.decode(string_data);
return gl.getAttribLocation(js_objects[program], string);
},
linkProgram: function (program) {
gl.linkProgram(js_objects[program]);
},
shaderSource: function (shader, pointer, length) {
const string_data = new Uint8Array(wasm_memory.buffer, pointer, length);
const string = decoder.decode(string_data);
gl.shaderSource(js_objects[shader], string);
},
useProgram: function (program) {
gl.useProgram(js_objects[program]);
},
vertexAttribPointer: function (index, size, type, normalized, stride, offset) {
gl.vertexAttribPointer(index, size, type, normalized, stride, offset);
},
}
};
```
--------------------------------
### Creating a Fake Window for OpenGL Initialization
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
This snippet demonstrates the Win32 API calls required to create a temporary, invisible window. This window is used solely to obtain a device context (HDC) and choose a suitable pixel format for OpenGL initialization before the actual visible window is created.
```rust
let _atom = unsafe { register_class(&wc) }.unwrap();
// fake window stuff
let pfd = PIXELFORMATDESCRIPTOR {
dwFlags: PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
iPixelType: PFD_TYPE_RGBA,
cColorBits: 32,
cDepthBits: 24,
cStencilBits: 8,
iLayerType: PFD_MAIN_PLANE,
..Default::default()
};
let fake_hwnd = unsafe {
create_app_window(
sample_window_class,
"Fake Window",
None,
[1, 1],
null_mut(),
)
}
.unwrap();
let fake_hdc = unsafe { GetDC(fake_hwnd) };
let pf_index = unsafe { choose_pixel_format(fake_hdc, &pfd) }.unwrap();
// TODO: SetPixelFormat
assert!(unsafe { ReleaseDC(fake_hwnd, fake_hdc) } != 0);
assert!(unsafe { DestroyWindow(fake_hwnd) } != 0);
// real window stuff
let lparam: *mut i32 = Box::leak(Box::new(5_i32));
```
--------------------------------
### Handle WM_NCCREATE and WM_CREATE messages
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Implement the window procedure to handle WM_NCCREATE and WM_CREATE messages. Initially, these messages are logged and a default return value is provided.
```rust
// in the window_procedure
match Msg {
WM_NCCREATE => {
println!("NC Create");
}
WM_CREATE => println!("Create"),
```
--------------------------------
### Rust Bindings for JavaScript WebGL Functions
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/web_stuff/web_gl_with_bare_wasm.md
This Rust code defines external functions that correspond to JavaScript functions for canvas setup and clearing. These are used to call JavaScript from WebAssembly.
```rust
mod js {
extern "C" {
pub fn setupCanvas();
pub fn clearToBlue();
}
}
#[no_mangle]
pub extern "C" fn start() {
unsafe {
js::setupCanvas();
js::clearToBlue();
}
}
```
--------------------------------
### Creating and Making an OpenGL Context Current (Win32)
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
This Rust code snippet demonstrates how to create an OpenGL 3.3 Core profile context using the `do_wglCreateContextAttribsARB` wrapper. It configures context flags, including debug flags for development builds, and then makes the newly created context current for the specified device context.
```rust
// now we create a context.
const FLAGS: c_int = WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
| if cfg!(debug_assertions) { WGL_CONTEXT_DEBUG_BIT_ARB } else { 0 };
let hglrc = unsafe {
do_wglCreateContextAttribsARB(
wglCreateContextAttribsARB,
hdc,
null_mut(),
&[
[WGL_CONTEXT_MAJOR_VERSION_ARB, 3],
[WGL_CONTEXT_MINOR_VERSION_ARB, 3],
[WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB],
[WGL_CONTEXT_FLAGS_ARB, FLAGS],
[0, 0],
],
)
} .unwrap();
unsafe { wgl_make_current(hdc, hglrc) }.unwrap();
unsafe { (*lparam).hglrc = hglrc };
```
--------------------------------
### Get Last Error Code
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
Retrieves the last error code from the thread-local storage using the `GetLastError` Win32 API function. This function is wrapped to return a `Win32Error` type.
```rust
/// Gets the thread-local last-error code value.
///
/// See [`GetLastError`](https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror)
pub fn get_last_error() -> Win32Error {
Win32Error(unsafe { GetLastError() })
}
```
--------------------------------
### Window Procedure with WM_PAINT Handling
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Implements the window procedure to handle WM_PAINT messages by painting the window's client area.
```rust
pub unsafe extern "system" fn window_procedure(
hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM,
) -> LRESULT {
match Msg {
WM_CLOSE => drop(DestroyWindow(hWnd)),
WM_DESTROY => PostQuitMessage(0),
WM_PAINT => {
let mut ps = PAINTSTRUCT::default();
let hdc = BeginPaint(hWnd, &mut ps);
let _success = FillRect(hdc, &ps.rcPaint, (COLOR_WINDOW + 1) as HBRUSH);
EndPaint(hWnd, &ps);
}
_ => return DefWindowProcW(hWnd, Msg, wParam, lParam),
}
0
}
```
--------------------------------
### Debug Formatting for Win32Error
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Implements the `Debug` trait for `Win32Error` to display a human-readable error message using `FormatMessageW`. Includes an example of formatting a successful operation and a custom application error.
```rust
impl core::fmt::Debug for Win32Error {
/// Displays the error using `FormatMessageW`
///
/// ```
/// use triangle_from_scratch::win32::*;
/// let s = format!("{:?}", Win32Error(0));
/// assert_eq!("The operation completed successfully. ", s);
/// let app_error = format!("{:?}", Win32Error(1 << 29));
/// assert_eq!("Win32ApplicationError(536870912)", app_error);
/// ```
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
// everything from before
}
}
```
--------------------------------
### Initialize UTF-16 Code Unit Counter
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/appendix/utf16_literals.md
This const function initializes the counting of UTF-16 code units for a given string slice. It serves as a starting point for determining buffer capacity.
```rust
pub const fn count_utf16_code_units(s: &str) -> usize {
0
}
```
--------------------------------
### Return 1 for WM_NCCREATE
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Modify the window procedure to return 1 for WM_NCCREATE messages to allow window creation to proceed. This is crucial for successful window initialization.
```rust
// in the window_procedure
WM_NCCREATE => {
println!("NC Create");
return 1;
}
```
--------------------------------
### Loading OpenGL Library and Functions in Win32
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
This code snippet demonstrates loading the opengl32.dll library and then calling the load_gl_functions method on the window data to initialize OpenGL function pointers.
```rust
let opengl32 = load_library("opengl32.dll").unwrap();
unsafe { (*lparam).opengl32 = opengl32 };
unsafe { (*lparam).load_gl_functions() };
```
--------------------------------
### ShowWindow Function Signature and Constant (Rust)
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Defines the ShowWindow function signature and the SW_SHOW constant for making a window visible. Requires linking to User32.dll.
```rust
const SW_SHOW: c_int = 5;
type BOOL = c_int;
#[link(name = "User32")]
extern "system" {
/// ["ShowWindow"](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow)
pub fn ShowWindow(hWnd: HWND, nCmdShow: c_int) -> BOOL;
}
```
--------------------------------
### Basic Window Procedure Stub
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
A minimal, unsafe external system function stub for a window procedure that currently returns 0 for all messages. This serves as a starting point before implementing message handling.
```rust
pub unsafe extern "system" fn window_procedure(
hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM,
) -> LRESULT {
0
}
```
--------------------------------
### Lookup and Call wglGetExtensionsStringARB
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Demonstrates the inline process of looking up the `wglGetExtensionsStringARB` function pointer, calling it with a device context, and processing the returned null-terminated string.
```rust
unsafe { wgl_make_current(fake_hdc, fake_hglrc) }.unwrap();
#[allow(non_camel_case_types)]
type wglGetExtensionsStringARB_t =
unsafe extern "system" fn(HDC) -> *const c_char;
let wgl_get_extension_string_arb: Option = unsafe {
core::mem::transmute(
wgl_get_proc_address(c_str!("wglGetExtensionsStringARB")).unwrap(),
)
};
let mut extension_string: *const u8 =
unsafe { (wgl_get_extension_string_arb.unwrap())(fake_hdc) }.cast();
assert!(!extension_string.is_null());
let mut s = String::new();
unsafe {
while *extension_string != 0 {
s.push(*extension_string as char);
extension_string = extension_string.add(1);
}
}
println!("> Extension String: {}", s);
// cleanup the fake stuff
```
--------------------------------
### Setting up Pixel Format Attributes
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
This code snippet demonstrates how to construct the attribute list for `wglChoosePixelFormatARB`. It includes base requirements and conditionally adds extensions like sRGB and multisampling. The list is finalized by appending a zero-value pair before calling the pixel format selection function.
```Rust
// base criteria
let mut int_attribs = vec![
[WGL_DRAW_TO_WINDOW_ARB, true as _],
[WGL_SUPPORT_OPENGL_ARB, true as _],
[WGL_DOUBLE_BUFFER_ARB, true as _],
[WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB],
[WGL_COLOR_BITS_ARB, 32],
[WGL_DEPTH_BITS_ARB, 24],
[WGL_STENCIL_BITS_ARB, 8],
];
// if sRGB is supported, ask for that
if wgl_extensions.iter().any(|s| s == "WGL_EXT_framebuffer_sRGB") {
int_attribs.push([WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT, true as _]);
};
// let's have some multisample if we can get it
if wgl_extensions.iter().any(|s| s == "WGL_ARB_multisample") {
int_attribs.push([WGL_SAMPLE_BUFFERS_ARB, 1]);
};
// finalize our list
int_attribs.push([0, 0]);
// choose a format, get the PIXELFORMATDESCRIPTOR, and set it.
let pix_format = unsafe {
do_wglChoosePixelFormatARB(wglChoosePixelFormatARB, hdc, &int_attribs, &[])
}
.unwrap();
let pfd = unsafe { describe_pixel_format(hdc, pix_format) }.unwrap();
unsafe { set_pixel_format(hdc, pix_format, &pfd) }.unwrap();
```
--------------------------------
### Get Max Pixel Format Index (Win32 API)
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
A Rust wrapper for `DescribePixelFormat` to retrieve the maximum pixel format index available for a given device context. Pixel format indexes are 1-based.
```rust
/// Gets the maximum pixel format index for the HDC.
///
/// Pixel format indexes are 1-based.
///
/// To print out info on all the pixel formats you'd do something like this:
/// ```no_run
/// # use triangle_from_scratch::win32::*
/// let hdc = todo!("create a window to get an HDC");
/// let max = unsafe { get_max_pixel_format_index(hdc).unwrap() };
/// for index in 1..=max {
/// let pfd = unsafe { describe_pixel_format(hdc, index).unwrap() };
/// todo!("print the pfd info you want to know");
/// }
/// ```
///
/// See [`DescribePixelFormat`](https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-describepixelformat)
pub unsafe fn get_max_pixel_format_index(
hdc: HDC,
) -> Result {
let max_index = DescribePixelFormat(
hdc,
1,
size_of::() as _,
null_mut(),
);
if max_index == 0 {
Err(get_last_error())
} else {
Ok(max_index)
}
}
```
--------------------------------
### Get HINSTANCE using GetModuleHandleW
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
This snippet demonstrates how to obtain the HINSTANCE of the current process's executable file using the `GetModuleHandleW` function from the Win32 API. It's used when initializing window structures.
```rust
fn main() {
let hInstance = GetModuleHandleW(core::ptr::null());
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(dummy_window_procedure);
wc.hInstance = hInstance;
wc.lpszClassName = todo!();
}
```
--------------------------------
### Unsafe Get Window Userdata Pointer
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
An unsafe Rust function to retrieve the 'userdata' pointer of a Win32 window. It includes error checking similar to the setter and allows specifying the expected pointer type.
```rust
/// Gets the "userdata" pointer of the window (`GWLP_USERDATA`).
///
/// **Returns:** The userdata pointer.
///
/// [`GetWindowLongPtrW`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getwindowlongptrw)
pub unsafe fn get_window_userdata(hwnd: HWND) -> Result<*mut T, Win32Error> {
set_last_error(Win32Error(0));
let out = GetWindowLongPtrW(hwnd, GWLP_USERDATA);
if out == 0 {
// if output is 0, it's only a "real" error if the last_error is non-zero
let last_error = get_last_error();
if last_error.0 != 0 {
Err(last_error)
} else {
Ok(out as *mut T)
}
} else {
Ok(out as *mut T)
}
}
```
--------------------------------
### Simplified Rust App Window Creation
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
A simplified Rust function for creating application windows, abstracting complex Win32 API parameters into more manageable arguments. It uses default styles and handles string conversions internally.
```rust
pub unsafe fn create_app_window(
class_name: &str,
window_name: &str,
position: Option<[i32; 2]>,
[width, height]: [i32; 2],
create_param: LPVOID,
) -> Result {
// ...
```
--------------------------------
### Process and Print OpenGL Extensions
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Demonstrates how to process the string returned by `wgl_get_extension_string_arb`, splitting it into individual extensions and collecting them into a `Vec`.
```rust
let extensions: Vec =
unsafe { wgl_get_extension_string_arb(fake_hdc) }
.map(|s| {
s.split(' ').filter(|s| !s.is_empty()).map(|s| s.to_string()).collect()
})
.unwrap_or(Vec::new());
println!("> Extensions: {:?}", extensions);
```
--------------------------------
### Incorrectly Assigning Wide String Pointer
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
This example demonstrates a common beginner mistake where a pointer to a temporary vector is assigned to a Win32 structure field. The vector is deallocated when the expression ends, leading to a dangling pointer and undefined behavior.
```rust
fn main() {
let hInstance = unsafe { GetModuleHandleW(core::ptr::null()) };
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(dummy_window_procedure);
wc.hInstance = hInstance;
// BAD, WRONG, NO
wc.lpszClassName = wide_null("Sample Window Class").as_ptr();
}
```
--------------------------------
### Window Procedure with WM_CLOSE and WM_DESTROY Handling
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Implements message handling for WM_CLOSE and WM_DESTROY. WM_CLOSE calls DestroyWindow, and WM_DESTROY calls PostQuitMessage. Other messages are passed to the default window procedure.
```rust
pub unsafe extern "system" fn window_procedure(
hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM,
) -> LRESULT {
match Msg {
WM_CLOSE => DestroyWindow(hWnd),
WM_DESTROY => PostQuitMessage(0),
_ => return DefWindowProcW(hWnd, Msg, wParam, lParam),
}
0
}
```
--------------------------------
### Usage of Safe RegisterClass Wrapper
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
Demonstrates how to use the safe `register_class` wrapper, including error handling by checking the returned Result and retrieving the last error code if registration fails.
```rust
let atom = unsafe { register_class(&wc) }.unwrap_or_else(|()| {
let last_error = unsafe { GetLastError() };
panic!("Could not register the window class, error code: {}", last_error);
});
```
--------------------------------
### Dummy Window Procedure
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
A placeholder window procedure that panics when called. This is used as a forward reference before the actual window procedure logic is implemented.
```rust
unsafe extern "system" fn dummy_window_procedure(
hwnd: HWND,
uMsg: UINT,
wParam: WPARAM,
lParam: LPARAM,
) -> LRESULT {
unimplemented!()
}
```
--------------------------------
### Main Function Cleanup for Fake Context
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Demonstrates the cleanup process for a temporary OpenGL context in a Win32 application, including deleting the context and releasing associated resources.
```rust
unsafe { set_pixel_format(fake_hdc, pf_index, &pfd) }.unwrap();
let fake_hglrc = unsafe { wgl_create_context(fake_hdc) }.unwrap();
// TODO: work with the fake context.
// cleanup the fake stuff
unsafe { wgl_delete_context(fake_hglrc) }.unwrap();
assert!(unsafe { release_dc(fake_hwnd, fake_hdc) });
unsafe { destroy_window(fake_hwnd) }.unwrap();
unsafe { unregister_class_by_atom(fake_atom, instance) }.unwrap()
```
--------------------------------
### Updating Window Class with Predefined Cursor
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
Demonstrates how to use the `load_predefined_cursor` function when setting up a `WNDCLASSW` structure in Rust. This shows the practical application of the safe wrapper, including handling the `Result` to obtain the cursor handle.
```Rust
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(window_procedure);
wc.hInstance = hinstance;
wc.lpszClassName = sample_window_class_wn.as_ptr();
wc.hCursor = load_predefined_cursor(IDCursor::Arrow).unwrap();
```
--------------------------------
### Correctly Load and Set Default Cursor
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
This code snippet demonstrates the correct way to load the default arrow cursor using `LoadCursorW` by passing `null_mut()` as the instance handle. This ensures the cursor is displayed correctly when the window is created, avoiding the issue where the cursor might disappear.
```rust
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(window_procedure);
wc.hInstance = hInstance;
wc.lpszClassName = sample_window_class_wn.as_ptr();
wc.hCursor = unsafe { LoadCursorW(null_mut(), IDC_ARROW) };
```
--------------------------------
### Handle WM_DESTROY with Userdata Cleanup
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
Demonstrates how to safely clean up the userdata pointer when a window is destroyed (`WM_DESTROY`). It retrieves the pointer using `get_window_userdata` and deallocates the associated memory if it's not null.
```rust
// in `window_procedure`
WM_DESTROY => {
match get_window_userdata::(hwnd) {
Ok(ptr) if !ptr.is_null() => {
Box::from_raw(ptr);
println!("Cleaned up the box.");
}
Ok(_) => {
println!("userdata ptr is null, no cleanup")
}
Err(e) => {
println!("Error while getting the userdata ptr to clean it up: {}", e)
}
}
PostQuitMessage(0);
}
```
--------------------------------
### Making and Unmaking OpenGL Context Current
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
Illustrates the process of making an OpenGL context current for rendering operations and then unmaking it before cleanup, following good practice for cross-platform compatibility.
```rust
let fake_hglrc = unsafe { wgl_create_context(fake_hdc) }.unwrap();
unsafe { wgl_make_current(fake_hdc, fake_hglrc) }.unwrap();
// TODO: work with the fake context.
// cleanup the fake stuff
unsafe { wgl_make_current(null_mut(), null_mut()) }.unwrap();
unsafe { wgl_delete_context(fake_hglrc) }.unwrap()
```
--------------------------------
### Basic Window Procedure with DefWindowProcW
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
This Rust code snippet demonstrates how to assign the default window procedure (DefWindowProcW) to a window class. It also shows the external function declaration for DefWindowProcW, which is necessary for handling window messages.
```rust
fn main() {
// ...
wc.lpfnWndProc = Some(DefWindowProcW);
// ...
}
#[link(name = "User32")]
extern "system" {
/// [DefWindowProcW](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowprocw)
pub fn DefWindowProcW(
hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM,
) -> LRESULT;
}
```
--------------------------------
### Safe BeginPaint Wrapper
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
Provides a safe Rust wrapper for the Win32 BeginPaint function. It returns a Result containing the HDC and PAINTSTRUCT on success, or a Win32Error on failure. This function prepares the specified window for painting.
```rust
/// Prepares the specified window for painting.
///
/// On success: you get back both the [`HDC`] and [`PAINTSTRUCT`]
/// that you'll need for future painting calls (including [`EndPaint`]).
///
/// [`BeginPaint`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-beginpaint)
pub unsafe fn begin_paint(
hwnd: HWND,
) -> Result<(HDC, PAINTSTRUCT), Win32Error> {
let mut ps = PAINTSTRUCT::default();
let hdc = BeginPaint(hwnd, &mut ps);
if hdc.is_null() {
Err(get_last_error())
} else {
Ok((hdc, ps))
}
}
```
--------------------------------
### Rust Wrapper for CreateWindowExW
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32_cleanup.md
A safe Rust wrapper around the Win32 API's CreateWindowExW function. It handles potential errors by returning a Win32Error if the window creation fails.
```rust
/// Creates a window.
///
/// See [`CreateWindowExW`](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw)
pub unsafe fn create_window_ex_w(
ex_style: DWORD,
class_name: LPCWSTR,
window_name: LPCWSTR,
style: DWORD,
x: c_int,
y: c_int,
width: c_int,
height: c_int,
parent: HWND,
menu: HMENU,
instance: HINSTANCE,
param: LPVOID,
) -> Result {
let hwnd = CreateWindowExW(
ex_style,
class_name,
window_name,
style,
x,
y,
width,
height,
parent,
menu,
instance,
param,
);
if hwnd.is_null() {
Err(get_last_error())
} else {
Ok(hwnd)
}
}
```
--------------------------------
### Using Wrapped Win32 API Functions
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/loading_opengl/win32.md
This snippet shows how to use the Rust wrapper functions for Win32 API calls, demonstrating the improved error handling with `Option` and `Result`. The use of `unwrap()` and `assert!` is shown, assuming the operations are expected to succeed in this context.
```rust
let fake_hdc = unsafe { get_dc(fake_hwnd) }.unwrap();
let pf_index = unsafe { choose_pixel_format(fake_hdc, &pfd) }.unwrap();
// TODO: SetPixelFormat
assert!(unsafe { release_dc(fake_hwnd, fake_hdc) });
unsafe { destroy_window(fake_hwnd) }.unwrap();
```
--------------------------------
### Configuring WNDCLASSW with Window Procedure
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
This snippet shows how to assign the dummy window procedure and placeholders for instance handle and class name to the WNDCLASSW struct.
```rust
fn main() {
let mut wc = WNDCLASSW::default();
wc.lpfnWndProc = Some(dummy_window_procedure);
wc.hInstance = todo!();
wc.lpszClassName = todo!();
}
```
--------------------------------
### Define WM_NCCREATE and WM_CREATE constants
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Define the constants for WM_NCCREATE and WM_CREATE messages. These are used to identify specific window messages.
```rust
const WM_NCCREATE: u32 = 0x0081;
const WM_CREATE: u32 = 0x0001;
```
--------------------------------
### Updating Window Class for Window Procedure
Source: https://github.com/rust-tutorials/triangle-from-scratch/blob/main/book_src/opening_a_window/win32.md
Shows how to assign the custom window procedure to the window class structure.
```rust
fn main() {
// ...
wc.lpfnWndProc = Some(window_procedure);
// ...
}
```