This tutorial will show how to compile a Win32 app for Windows, and show how to create a button, text entry and draw with Cairo.
Prerequisites:
For cairo run-time, I just installed the Gtk2 all-in-one bundle from here: http://www.gtk.org/download/win32.php
Either put the DLLs where the EXE file will be compiled, or add the path to the bin folder in your PATH environment variable.
I used Visual C++. Make sure you can use the compiler (type cl in the command line), if not add the environemnt variables for Visual C++ (there's a batch script called vcvars which will do it for you in Visual C++ programs folder)
For using MinGW, take a look at [1].
First, make sure you're able to compile and link against the Win32 API, with this minimal example:
import windows
discard MessageBox(0, "Hello World", "Nim", MB_ICONEXCLAMATION or MB_OK)
Compile and run this example with:
nim c --app:gui --passL:user32.lib -r wintest.nim
Now it's time to create some windows. You can use any example/tutorial based on C as an example. I used the example from [2].
Here's the major differences from C, apart from simple syntax:
In C, you get some parameters from the WinMain entry point[5]:
HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow
These do not seem to be available in Nim yet. You can get hInstance with this call: GetModuleHandle(nil). I think you can get nCmdShow from GetStartupInfo [3]. And you can use GetCommandLine() instead of lpCmdLine [4]. hPrevInstance is not used for anything.
Okay, so here is the final result:
https://gist.github.com/skyfex/74aba74ad1143ffe6c35
In this example, I've also added example code to add a standard text field, and a button (in the WM_CREATE message). And I've added an example for how to draw with Cairo (in the WM_PAINT message). In my example there's some flickering when the window is redrawn. It should be possible to remove that, for instance by setting hbrBackground to 0, and drawing the background yourself with Cairo.
If you compile this as shown above, you will get old Windows 98 style controls. If you want the button style to match the visual style of Windows 7 or whatever you're using, you need to add a manifest file. This is described in [1].
Create a file wintest.manifest with this content: https://gist.github.com/skyfex/4d6b2b6c446cfaaa6695
And create a resource file wintest.rc:
#include <windows.h>
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "wintest.manifest"
Compile the resource file with this command: rc wintest.rc
Now you can compile your app with the manifest included:
nim c --app:gui --passL:user32.lib --passL:wintest.RES -r wintest.nim
I might put this and similar examples for Mac OS X, X11 and GTK up on Github soon. It should make for a decent bootstrap for future cross-platform Nim GUI app projects.
import windows
#var hinst = GetModuleHandle(nil)
#echo repr hinst
proc wndfunc(hwnd: HWND, msg: WINUINT, wparam: WPARAM, lparam: LPARAM): LRESULT{.stdcall.} =
case msg
of WM_CREATE:
discard MessageBox(hwnd, "Hello Nim", nil, 0)
of WM_DESTROY:
PostQuitMessage(0)
else:
result = DefWindowProc(hwnd, msg, wparam, lparam)
var class_name = "app"
var wc:WNDCLASS
wc.style = 0
wc.lpfnWndProc = wndfunc
wc.cbClsExtra = 0
wc.cbWndExtra = 0
wc.hInstance = 0
wc.hIcon = 0
wc.hCursor = 0
wc.hbrBackground = GetStockObject(BLACK_BRUSH)
wc.lpszMenuName = nil
wc.lpszClassName = class_name
if RegisterClass(wc) == 0:
echo "Failed to register class"
var hwnd = CreateWindow(class_name, "Nim windows", WS_OVERLAPPEDWINDOW, 100, 100, 240, 160, 0, 0, 0, nil)
discard ShowWindow(hwnd, SW_SHOW);
discard UpdateWindow(hwnd)
var msg:MSG
while GetMessage(addr msg, 0, 0, 0) != 0:
discard TranslateMessage(addr msg)
discard DispatchMessage(addr msg)
For practicem, I've wrote a winapi gui example. http://my.oschina.net/angluca/blog/491008i386.windows.gcc.path = "/usr/bin"
i386.windows.gcc.exe = "i686-w64-mingw32-gcc"
i386.windows.gcc.linkerexe = "i686-w64-mingw32-gcc"