Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Creating A Window In Go Language

5.00/5 (7 votes)
1 Dec 2015CPOL4 min read 38.3K   914  
This tip describes how we can create a simple window in Go programming language using Win32 API functions.

Introduction

This tip describes how we can create a simple window in Go programming language using Win32 API functions.

This tip only shows the steps of creating a simple window in Go. For getting more information about the Go language, you can visit Go Document website - https://golang.org/doc.

Introduction To Go (Taken From https://golang.org)

Go is an open source programming language that makes it easy to build simple, reliable, and efficient software.

Go is expressive, concise, clean, and efficient. Its concurrency mechanisms make it easy to write programs that get the most out of multicore and networked machines, while its novel type system enables flexible and modular program construction. Go compiles quickly to machine code yet has the convenience of garbage collection and the power of run-time reflection. It's a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language.

Using the Code

I assume that you have the basic knowledge on Win32 API.

For this project, I’ve used the 1.5.1 64-bit version of Go.

To use Win32 API in Go language, we need the ‘w32’ package. The package can be found on Git Hub website - https://github.com/AllenDang/w32

Here is our Window creation code:

The first statement in a Go source file must be package name. Since our program is an executable program, so the package name must be main. It tells the Go compiler that the package should compile as an executable program instead of a shared library:

package main

In Go, import keyword is used for importing package into other packages. So, we import our necessary packages using the import keyword in this way:

import "./w32" // I had putted the w32 package inside the project source folder -

We also need to import the following packages:

import "syscall"
import "unsafe"

Unsafe is a built-in package of Go language. It provides facilities for low-level programming including operations that violate the type system. We need it for converting uintptr type to pointer and also the package contains a function called Sizeof. We will use the Sizeof function to get the size of WNDCLASSEX structure.

This is a simple windows resource id to uint16 pointer converter function. We need it to pass the IDI_APPLICATION and IDC_ARROW constant to LoadIcon and LoadCursor function argument. In Go, type conversion expression is T(v) where it converts the value v to the type T:

func MakeIntResource(id uint16) (*uint16) {
    return (*uint16)(unsafe.Pointer(uintptr(id)))
}

This is our window message handler function which handles only the WM_DESTROY message to make sure that our window will close properly on close event:

func WndProc(hWnd w32.HWND, msg uint32, wParam, lParam uintptr) (uintptr) {
switch msg {
case w32.WM_DESTROY:
        w32.PostQuitMessage(0)
    default:
        return w32.DefWindowProc(hWnd, msg, wParam, lParam)
    }
    return 0
}

The following WinMain function creates our window and it runs a standard application loop:

func WinMain() int {

Get our application instance handle in a local variable called hInstance. In Go language, the := operator works as a declaration and as initialization at once:

hInstance := w32.GetModuleHandle("")

Since w32 package defines only Unicode (UTF16) compatible WinAPI functions, so we have to use the StringToUTF16Ptr function from syscall package to convert Go string type to UTF16 pointer:

lpszClassName := syscall.StringToUTF16Ptr("WNDclass")

Here we declare variable using ‘var’ keyword:

var wcex w32.WNDCLASSEX

Assignments are simply done using ‘=’ operator:

wcex.Size            = uint32(unsafe.Sizeof(wcex))
wcex.Style         = w32.CS_HREDRAW | w32.CS_VREDRAW
wcex.WndProc       = syscall.NewCallback(WndProc)
wcex.ClsExtra        = 0
wcex.WndExtra        = 0
wcex.Instance         = hInstance
wcex.Icon         = w32.LoadIcon(hInstance, MakeIntResource(w32.IDI_APPLICATION))
wcex.Cursor       = w32.LoadCursor(0, MakeIntResource(w32.IDC_ARROW))
wcex.Background = w32.COLOR_WINDOW + 11

In Go language, nil is equivalent of NULL. Since we are not providing any menu for our window, we assign the MenuName field with nil:

wcex.MenuName  = nil

wcex.ClassName = lpszClassName
wcex.IconSm       = w32.LoadIcon(hInstance, MakeIntResource(w32.IDI_APPLICATION))

Here, we register our class using RegisterClassEx function of w32 package. We pass the address of wcex variable to its parameter -

w32.RegisterClassEx(&wcex)

Then we create our window using CreateWindowEx function of w32 package. Our window size will be 400x400:

hWnd := w32.CreateWindowEx(
0, lpszClassName, syscall.StringToUTF16Ptr("Simple Go Window!"), 
w32.WS_OVERLAPPEDWINDOW | w32.WS_VISIBLE, 
w32.CW_USEDEFAULT, w32.CW_USEDEFAULT, 400, 400, 0, 0, hInstance, nil)

We use the ShowWindow function of w32 package to show our window on screen:

w32.ShowWindow(hWnd, w32.SW_SHOWDEFAULT)
w32.UpdateWindow(hWnd)

The following codes will run standard application loop until we close our window. It will be trying to get message from our window:

   var msg w32.MSG
   for {
        if w32.GetMessage(&msg, 0, 0, 0) == 0 {
            break
        }
        w32.TranslateMessage(&msg)
        w32.DispatchMessage(&msg)
   }
   return int(msg.WParam)
}

This is our program entry point function. It calls the WinMain function to create and show our window:

func main() {
    WinMain()
    return
}

Now we have our source code. I’ve used main.go as the source file name.

Compile the source file using the following commands:

go.exe build -ldflags "-H windowsgui" main.go

The ‘ -ldflags "-H windowsgui" ‘ flags will remove the black console window from our application.

Now, run the main.exe file and see your Simple Go Window!

Request to Readers

If you have any ideas about a new project on Go language that will help people to learn the language more easily, you can inform me through comments.

Conclusion

Go is a very nice programming language. We should use it wisely to get proper benefits from it. And I hope, this tip has helped beginner programmers.

License

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