How Can I Create a GUI Using C Programming?


In most applications you have some sort of widgets like buttons, dialogs, sliders, etc. Even in Games you have at least the menu and options dialogs where you might need them. So if you program your Game entirely in C, how can you create a Graphical User Interface (GUI)?

Gtk+ is the best way to create a Graphical User Interface (GUI) in C. It is portable, written in pure C and easy to include and use. There are other options such as Windows API and XForms, both of which are operating system dependent.

Gtk+ Widgets Example
Example of Gtk+ Widgets in action

These may not be the only options but they are definitely the most well-known. Let’s have a deeper look into what they can do and how it works.

How To Create a GUI in C

The C Programming Language itself has no widgets or other ui elements. Therefore you have to relate on either the API of your operating system or dedicated graphics (widgets) libraries. Please note that widgets are different from drawing just shapes (on which you can read about here) because they provide specific functionalities.

The Windows API gives the programmer the possibility to create windows and widgets while using native windows libraries. It is well documented and was used by many (Game) programmers in the 90s.

XForms (not to be consfused with XML->XForms) for Linux and Unix systems is a library that uses the X11 Server technology. It is therefore bound to systems that support X11 and no option on windows systems.

The GTK library (Gtk+ as part of it) is a multi-platform library written in C. It supports lots of widgets and is easily programmable and also well documented. I think this is the best option because you have the portability as well as easy to use code. The setup on windows is a little bit painful though, because you have to use the package manager pacman which on windows only runs in the MYSYS2 UNIX-Like development environment.Opens in a new tab. You have to install MSYS2 first and then load Gtk+ via pacman.

The following paragraphs go a little bit into detail for each of this possibilities. There is a Hello World like example in conjunction with the corresponding screenshot. This way you have a first impression for your comparison and decision making process.

GTK+ (GNU Image Manipulation Program Toolkit)

Gtk+ is a library for creating user interfaces. It is portable to Microsoft Windows, Linux and MacOS. You can download the current version at their homepageOpens in a new tab.. The library is written in pure C and therefore the best option if you want portable and easy widgets for your C program.

It is easy to write code with Gtk+ and it also provides signals which are a good callback handling concept. The Hello World program with Gtk+ would look like this:

#include <gtk/gtk.h> 
 
int main(int argc, char** argv) 
{ 
  gtk_init(&argc, &argv); 
  GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
  gtk_window_set_title(GTK_WINDOW (window), "Hello World!"); 
  gtk_window_set_default_size(GTK_WINDOW (window), 200, 200); 
  g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL); 
  gtk_widget_show(window); 
  gtk_main(); 
 
  return 0; 
} 

When compiled, linked and run, the output of this program would be the following:

Gtk+ Hello World
“Hello World” with Gtk+

The image at the beginning of this article shows the possibilities that you have with Gtk+. It’s a little more impressive then this Hello World screenshot, but anyways, there was not much coded in order to create this simple window.

Windows API

The Windows API is a good way for windows programmers to create graphical windows programs. It is well documented and available by default on windows operating systems. The downside is that it can be cumbersome and hard to program. It also feels somewhat outdated. It is nevertheless a good alternative when you don’t care about portability.

A very basic Hello World application would be to just show a MessageBox with a text and no real window.

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdLine, int cmdShow)
{
    MessageBox(NULL, TEXT("Hello WinAPI Graphical User Interface"), TEXT("Welcome"), 0);
    return 0;
}

A more sophisticated example is shown below. Here we create a real window and draw our Text on the screen with a coloured background.

This example is mostly taken from the Book “Programming Windows” from Charles Petzold as it is widely regarded as a standard developer reference for the Windows API. I nevertheless made some modifications for convenience.

#include <windows.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance, PSTR cmdLine, int cmdShow)
{
    static TCHAR appName[] = TEXT("Hello WindowsAPI");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = appName;

    if(!RegisterClass(&wndclass)) {
        MessageBox(NULL, TEXT("Could not register Window Class!"), appName, MB_ICONERROR);
    }

    hwnd = CreateWindow(appName, TEXT("The Hello Windows Program"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
    
    ShowWindow(hwnd, cmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    HDC hdc;
    PAINTSTRUCT ps;
    RECT rect;

    switch (message)
    {
    case WM_CREATE:
        /* Add Initialization Code */
        return 0;
    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);
        DrawText(hdc, TEXT("This is your first Windows Window!"),-1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
        EndPaint(hwnd, &ps);
        return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        break;
    }

    return DefWindowProc(hwnd, message, wParam, lParam);
}

This is a lot of Setup code for actually very little output. But keep in mind that you also implemented the Main Event Loop here so that reduces the work for further extensions of the Software. The result, however, looks like this:

WinAPI Hello World
“Hello World” with the Windows API

XForms (Forms Library for “X”)

If you are programming und Linux or Unix based systems and don’t like the Gtk+ then you could use XForms (which you can get hereOpens in a new tab.).

Programming with XForms is similar to Gtk+. You initialize it and create a window where you can put your other widgets. The classic Hello World with XForms looks like this:

#include <forms.h>

int main(int argc, char **argv)
{
    FL_FORM *form;

    fl_initialize(&argc, argv, 0, 0, 0);

    form = fl_bgn_form(FL_UP_BOX, 230, 100);
    fl_add_button(FL_NORMAL_BUTTON, 20, 20, 190, 60, "Hello world");
    fl_end_form();
 
    fl_show_form(form, FL_PLACE_MOUSE, FL_FULLBORDER, "Hello, world!");

    fl_do_forms();

    fl_hide_form(form);
    fl_finish();
    return 0;
}

The resulting output of this very basic example looks like this:

XForms Hello World
“Hello World” with XForms

Depending on your operating system you can try out the different options. As for the time of writing this article, I would go for Gtk+ when creating Graphical User Interfaces with C.

Marco Lieblang

Professional Programmer since 2003, passionate Programmer since the mid 90's. Developing in many languages from C/C++ to Java, C#, Python and some more. And I also may know a bit about Assembly Languages and Retro Systems.

Recent Posts