Click here to Skip to main content
13,708,880 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

32.1K views
570 downloads
7 bookmarked
Posted 10 Nov 2015
Licenced CPOL

Win32 GUI Programming In Rust Language

, 12 Dec 2016
Rate this:
Please Sign up or sign in to vote.
In this tip, we will see how we can use the Rust language to do GUI (Graphical User Interface) programming. As an example program, we will create a simple Window. Using Win32 API functions.

Introduction

Rust is a general-purpose, multi paradigm, compiled programming language. It is designed to be a fast, secured and type-safe language. The language is Open-Source and developed by Mozilla Research.

According to https://en.wikipedia.org/wiki/Rust_(programming_language) -

Although its development is sponsored by Mozilla, it is an open community project.

Rust supports both Functional and Object-Oriented programming. It supports C/C++ like pointer manipulation. So what we do in C/C++ language, we can do in Rust language, but in a very different way.

Rust Language Featuring (Taken From https://www.rust-lang.org/):

  • zero-cost abstractions
  • move semantics
  • guaranteed memory safety
  • threads without data races
  • trait-based generics
  • pattern matching
  • type inference
  • minimal runtime
  • efficient C bindings

In this tip, we will see how we can use this language to do GUI (Graphical User Interface) programming. As an example program, we will create a simple Window. Using Win32 API functions.

Using the Code

As far as I know, libraries are called Crates in Rust language. We are going to use various crates libraries in this project. libc, winapi, etc. Those crates are available in Rust crate host website (https://crates.io/).

Crates are automatically downloaded when you build your project using Cargo tool.

The Cargo is a tool for Rust language that helps in managing Rust projects. It comes with Rust official installer. The Cargo tool downloads all the dependencies needed for the project, builds dependencies and builds the project. Cargo tool helps programmer to build Rust project nicely. So we better use Cargo to make things easier.

To use the Cargo tool in our project, first we have to follow some rule. We have to create a root folder. The folder name should be your project name. Inside the root folder, we need to create an another folder called ‘src’ for keeping project source files. Because the Cargo tool expects the project source files inside a src directory and then, inside the root folder, we need to create a configuration file called ‘Cargo.toml’. The file is in TOML format which is similar to INI file but has some extra advantage.

Create the ‘Cargo.toml’ file and write the following lines of code to it:

[package]

name = "simple_window"
version = "0.0.1"
authors = [ "Your name <you@example.com>" ]

Then, add the following dependencies in the ‘Cargo.toml’ file:

[dependencies]

libc = "0.1.10"
winapi = "0.2.4"
user32-sys = "0.1.2"
kernel32-sys = "0.1.4"

First, we extern the following necessary crates in our main source file called ‘main.rs’. I assume that you are familiar with pure Win32 API functions:

extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;

Then we ‘use’ necessary types and functions from those libraries:

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

The following function is used to convert normal string to wide string:

fn to_wstring(str : &str) -> Vec<u16> {
    let v : Vec<u16> =
            OsStr::new(str).encode_wide().chain(Some(0).into_iter()).collect();
    v
}

This is our window message handler function. Currently, it only processes the WM_DESTROY message to exit our window properly on close event.

pub unsafe extern "system" fn window_proc(h_wnd :HWND, 
	msg :UINT, w_param :WPARAM, l_param :LPARAM) -> LRESULT
{
    if msg == winapi::winuser::WM_DESTROY {
        user32::PostQuitMessage(0);
    }
    return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
}

You may have noticed that we have used an ‘unsafe’ keyword in the above codes. According to https://doc.rust-lang.org/book/unsafe.html:

Rust’s main draw is its powerful static guarantees about behavior. But safety checks are conservative by nature: there are some programs that are actually safe, but the compiler is not able to verify this is true. To write these kinds of programs, we need to tell the compiler to relax its restrictions a bit. For this, Rust has a keyword, unsafe. Code using unsafe has less restrictions than normal code does.

So that’s why we have to use the unsafe keyword.

The following function hides the Console Window since we are building a GUI application. (Actually, I don’t know how to use ‘subsytem’ with Cargo tool! If someone knows, then please comment to improve this tip. :-> )

fn hide_console_window() 
{
    let window = unsafe {
        kernel32::GetConsoleWindow()
    };

    if window != std::ptr::null_mut() {
        unsafe {
            user32::ShowWindow (window, winapi::SW_HIDE)
        };
    }
}

The following is the entry point function of our program. We create our window inside this function by using the typical Win32 GUI programming style:

fn main()
{
  // Here our unsafe code goes - 
  unsafe 
  {
    // First we hide the console window - 
    hide_console_window();

    // Then we initialize WNDCLASS structure - 

    let class_name = to_wstring("my_window");

    let wnd = WNDCLASSW {
        style: 0,
        lpfnWndProc: Some(window_proc), 
        cbClsExtra: 0,
        cbWndExtra: 0,
        hInstance: 0 as HINSTANCE,
        hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
        hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
        hbrBackground: 16 as HBRUSH,
        lpszMenuName: 0 as LPCWSTR,
        lpszClassName: class_name.as_ptr(),
    };

    // We register our class - 
    user32::RegisterClassW(&wnd);

    let h_wnd_window = user32::CreateWindowExW(0, class_name.as_ptr(), 
                       to_wstring("Simple Window").as_ptr(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, 
                       0, 0, 400, 400, 0 as HWND, 0 as HMENU, 0 as HINSTANCE, std::ptr::null_mut());

    let mut msg = winapi::winuser::MSG {
        hwnd : 0 as HWND,
        message : 0 as UINT,
        wParam : 0 as WPARAM,
        lParam : 0 as LPARAM,
        time : 0 as DWORD,
        pt : winapi::windef::POINT { x: 0, y: 0, },
    };

    user32::ShowWindow(h_wnd_window, winapi::SW_SHOW);

    // Finally we run the standard application loop - 
    loop
    {   
        let pm = user32::GetMessageW(&mut msg, 0 as HWND, 0, 0);
        if pm == 0 {
            break;
        }

        if msg.message == winapi::winuser::WM_QUIT {
            break;
        }

        user32::TranslateMessage(&mut msg);
        user32::DispatchMessageW(&mut msg);
    }      
  }
}

Conclusion

Rust is a nice programming language. Programmers can learn this language to enhance their skill on programming.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Forhad Reza
Software Developer
Bangladesh Bangladesh
আমি একজন লেখক। নিয়মিত বিজ্ঞান বিষয়ে লিখছি। আমি সবসময় এই আশঙ্কায় থাকি যে কখন একজন লেখক ও লেখকের পরিবারের সদস্যদের ওপর বিনাদোষে অনাকাঙ্ক্ষিত দুঃখজনক পরিস্থিতি এসে পড়ে।

I'm a Bangladeshi and a citizen of Bangladesh living in Dhaka. I'm 18 years old and I've lots of experiences on computer programming. Followings are my current skills:

- Kernel (Windows & Linux) research (which is the heart of any operating system).
- Compiler design and implement.
- Expert in C, C++ and Visual Basic.
- I've the knowledge and basic experience on some other languages such as C#, D, Java etc.
- I believe I'm also good in F# language.
- Database programming.
- The world toughest programming language called Assembly, I can use it very easily.
- Working with Mozilla’s Rust & Google’s GO programming language for software development.
- Code optimization for performance.
- Multi-threaded programming in C/C++ and Java.
- Know various advanced computer algorithm and have used them to develop graphics and simulation programs. Also working with Linear Algebra and keen to learn Quadratic Algebra in future.
- Graphics and Game programming (Both 2D and 3D).

Currently, I'm doing researches on compiler and programming language development. I've made various kind of software and now I want to share my experience with people.

I love my country very much and I love all the peoples of my country. In fact, I love all the peoples live in this world. I love my country's independence. Since I'm becoming a writer, I feel insecure due to the fact that there are a lot of fake blames that are given to writers when they are totally innocent. It will happen as well as with their family.

Despite this bad situation, I'm proud of being Bengali and a Bangladeshi writer. I'm trying to take steps towards working on Computer Programming and also on Scientific subjects for my country. But it is too far from being a success and will require a lot of time due to my family's economic position.

Comments and Discussions

 
SuggestionI don't know Win32 but I do know some Rust and... Pin
Stephan Sokolow15-Dec-16 9:09
professionalStephan Sokolow15-Dec-16 9:09 
GeneralRe: I don't know Win32 but I do know some Rust and... Pin
Forhad Reza15-Dec-16 9:59
memberForhad Reza15-Dec-16 9:59 
QuestionMany problems in the code... Pin
raymai9727-Nov-16 1:48
memberraymai9727-Nov-16 1:48 
AnswerRe: Many problems in the code... Pin
Forhad Reza28-Nov-16 3:25
memberForhad Reza28-Nov-16 3:25 
AnswerRe: Many problems in the code... Pin
Forhad Reza11-Dec-16 23:44
memberForhad Reza11-Dec-16 23:44 
QuestionCompiled from source binary doesn't work. Pin
Member 128271091-Nov-16 7:08
memberMember 128271091-Nov-16 7:08 
AnswerRe: Compiled from source binary doesn't work. Pin
Member 128271093-Nov-16 6:32
memberMember 128271093-Nov-16 6:32 
GeneralRe: Compiled from source binary doesn't work. Pin
Forhad Reza14-Dec-16 6:43
memberForhad Reza14-Dec-16 6:43 
QuestionWindows 10 Pin
Member 79573371-Nov-16 6:24
memberMember 79573371-Nov-16 6:24 
QuestionBug in convert to wide_string Pin
nolemor18-Dec-15 21:39
membernolemor18-Dec-15 21:39 
AnswerRe: Bug in convert to wide_string Pin
Forhad Reza19-Dec-15 2:00
memberForhad Reza19-Dec-15 2:00 
GeneralRe: Bug in convert to wide_string Pin
15-Jun-16 14:23
member15-Jun-16 14:23 
GeneralRe: Bug in convert to wide_string Pin
Forhad Reza14-Dec-16 6:42
memberForhad Reza14-Dec-16 6:42 
SuggestionPlease don't stop writting Pin
3-Dec-15 8:51
member3-Dec-15 8:51 
GeneralRe: Please don't stop writting Pin
Forhad Reza4-Dec-15 21:24
memberForhad Reza4-Dec-15 21:24 
Questionconsole Pin
neko651-Dec-15 1:08
memberneko651-Dec-15 1:08 
AnswerRe: console Pin
Forhad Reza1-Dec-15 1:25
memberForhad Reza1-Dec-15 1:25 
GeneralRe: console Pin
neko651-Dec-15 2:25
memberneko651-Dec-15 2:25 
GeneralRe: console Pin
Forhad Reza1-Dec-15 2:43
memberForhad Reza1-Dec-15 2:43 
SuggestionRe: console Pin
Stephan Sokolow15-Dec-16 8:27
professionalStephan Sokolow15-Dec-16 8:27 
GeneralRe: console Pin
Forhad Reza15-Dec-16 9:55
memberForhad Reza15-Dec-16 9:55 
GeneralRe: console Pin
Rob Grainger2-Feb-17 11:44
memberRob Grainger2-Feb-17 11:44 
QuestionThanks! Pin
RossCanning27-Nov-15 10:27
memberRossCanning27-Nov-15 10:27 
AnswerRe: Thanks! Pin
Forhad Reza30-Nov-15 1:36
memberForhad Reza30-Nov-15 1:36 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web01-2016 | 2.8.180920.1 | Last Updated 12 Dec 2016
Article Copyright 2015 by Forhad Reza
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid