### 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); // ... } ```