Skip to content

Instantly share code, notes, and snippets.

@Ekopalypse
Last active March 10, 2023 10:57
Show Gist options
  • Save Ekopalypse/ad5732c9763c83342fcf1baa3b6b39cd to your computer and use it in GitHub Desktop.
Save Ekopalypse/ad5732c9763c83342fcf1baa3b6b39cd to your computer and use it in GitHub Desktop.
Basic Win32 Window
1. Download the file and extract it to a directory of your choice.
NOTE: You must also place a icon file named v-logo.ico in the directory.
2. change to this directory and create the resource file
# msvc - from a development shell
rc main.rc
# gcc
windres main.rc -O coff -o main.res
3. create the application like
v -cc msvc -cflags "CURRENT_DIRECTORY\main.res" -cflags "-ICURRENT_DIRECTORY" .
module main
fn C.EndDialog(hDlg voidptr, nResult isize) bool
fn C.DialogBoxW(hInstance voidptr, lpTemplate &u16, hWndParent voidptr, lpDialogFunc WndProc)
[callconv: stdcall]
fn about_dialog_proc(hwnd voidptr, message u32, wparam usize, lparam isize) isize {
match int(message) {
C.WM_COMMAND {
id := loword(u64(wparam))
if (id == C.IDOK) || ( id == C.IDCANCEL ) {
C.EndDialog(hwnd, id)
return 1
}
}
C.WM_INITDIALOG {
return 1
}
else {}
}
return 0
}
fn show_about_dialog(owner voidptr) {
C.DialogBoxW(voidptr(0), C.MAKEINTRESOURCE(C.IDD_ABOUTDIALOG), owner, WndProc(about_dialog_proc))
}
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="CompanyName.ProductName.YourApplication"
type="win32"
/>
<description>Your application description here.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>
module main
#flag -lComdlg32
#flag -lComctl32
#flag -lWinmm
#flag -lgdi32
#flag -mwindows
#include "commctrl.h"
#include "commdlg.h"
#include "mmsystem.h"
#include "resource.h"
fn C.CommDlgExtendedError() u32
fn C.InitCommonControls()
fn C.InitCommonControlsEx(picce &INITCOMMONCONTROLSEX) bool
fn C.MessageBoxW(voidptr, &u16, &u16, u32)
fn C.PlaySoundW(pszSound &u16, hmod voidptr, fdwSound u32) bool
fn C.BeginPaint(hWnd voidptr, lpPaint &PAINTSTRUCT) voidptr
fn C.GetClientRect(hWnd voidptr, lpRect &RECT) bool
fn C.DrawTextW(hdc voidptr, lpchText &u16, cchText int, lprc &RECT, format u32) int // format = C.DRAW_TEXT_FORMAT
fn C.EndPaint(hWnd voidptr, lpPaint &PAINTSTRUCT) bool
fn C.DefWindowProcW(hWnd voidptr, Msg u32, wParam usize, lParam isize) isize
fn C.LoadImageW(hInst voidptr, name &u16, image_type u32, cx int, cy int, fuLoad u32) voidptr // image_type = GDI_IMAGE_TYPE fuLoad IMAGE_FLAGS
fn C.LoadIconW(hInstance voidptr, lpIconName &u16) voidptr
fn C.LoadCursorW(hInstance voidptr, lpCursorName &u16) voidptr
fn C.GetStockObject(stock_type int) voidptr // C.GET_STOCK_OBJECT_FLAGS
fn C.RegisterClassExW(param0 &WNDCLASSEXW) u16
fn C.CreateWindowExW(
dwExStyle u32, lpClassName &u16, lpWindowName &u16, dwStyle u32,
X int, Y int, nWidth int, nHeight int, hWndParent voidptr, hMenu voidptr,
hInstance voidptr, lpParam voidptr) voidptr
fn C.ShowWindow(hWnd voidptr, nCmdShow bool) bool
fn C.UpdateWindow(hWnd voidptr) bool
fn C.GetMessageW(lpMsg &MSG, hWnd voidptr, wMsgFilterMin u32, wMsgFilterMax u32) int //MS defines this as bool but -1 is an expected value
fn C.TranslateMessage(lpMsg &MSG) bool
fn C.DispatchMessageW(lpMsg &MSG) isize
fn C.CreateAcceleratorTableW(paccel &ACCEL, cAccel int) voidptr
fn C.TranslateAcceleratorW(hWnd voidptr, hAccTable C.HACCEL, lpMsg &MSG) int
fn C.PostQuitMessage(nExitCode int)
fn C.GetModuleHandleW(lpModuleName &u16) voidptr
fn C.FindResourceW(hModule voidptr, lpName &u16, lpType &u16) voidptr
fn C.LoadResource(hModule voidptr, hResInfo voidptr) voidptr
fn C.LockResource(hResData voidptr) voidptr
fn C.FreeResource(hResData voidptr) bool
fn C.LoadAcceleratorsW(hInstance voidptr, lpTableName &u16) voidptr
fn C.TranslateAcceleratorW(hWnd voidptr, hAccTable voidptr, lpMsg &MSG) int
fn C.GetSystemMenu(hWnd voidptr, bRevert bool) voidptr
fn C.InsertMenuW(hMenu voidptr, uPosition u32, uFlags u32, uIDNewItem usize, lpNewItem &u16) bool
fn C.DestroyWindow(hWnd voidptr) bool
// macro
fn C.MAKEINTRESOURCE(dialogID int) voidptr
// helper functions
fn loword(value u64) u16 { return u16(value & 0xFFFF) }
fn hiword(value u64) u16 { return u16((value >>16) & 0xFFFF) }
// prototype of the window procedure callback
type WndProc = fn(hwnd voidptr, message u32, wparam usize, lparam isize) isize
#include <windows.h>
#include "resource.h"
IDI_HELLO ICON "v-logo.ico"
IDI_APPICON ICON "v-logo.ico"
IDR_MAINMENU MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", ID_FILE_EXIT
END
POPUP "&X"
BEGIN
MENUITEM "&About", ID_HELP_ABOUT
END
END
1 RT_MANIFEST "app.manifest"
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0, 0, 0, 1
PRODUCTVERSION 0, 0, 0, 1
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG | VS_FF_PRERELEASE
#else
FILEFLAGS 0
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" // 04b0 == 1200
BEGIN
VALUE "CompanyName", "company name"
VALUE "FileDescription", "file description"
VALUE "FileVersion", "file version"
VALUE "InternalName", "internal name"
VALUE "LegalCopyright", "(C)legal copyright"
VALUE "OriginalFilename", "original filename"
VALUE "ProductName", "product name"
VALUE "ProductVersion", "product version"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0409, 1200
END
END
/* Our "about" dialog */
IDD_ABOUTDIALOG DIALOGEX 0, 0, 200, 67
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
ICON IDI_APPICON,IDC_STATIC,7,7,20,20
LTEXT "Windows example application written in V", IDC_STATIC, 34, 7, 150, 8
DEFPUSHBUTTON "CLICK ME", IDOK, 90, 46, 50, 14, WS_GROUP
END
/* Our accelerators */
IDR_ACCELERATOR ACCELERATORS
BEGIN
"A", ID_HELP_ABOUT, VIRTKEY, CONTROL, SHIFT, ALT
0x70, ID_HELP_ABOUT, VIRTKEY // F1
END
module main
const (
app_name = "HelloV".to_wide()
)
struct INITCOMMONCONTROLSEX {
dw_size u32
dw_icc u32
}
struct RECT {
left int
top int
right int
bottom int
}
struct PAINTSTRUCT {
hdc voidptr
f_erase bool
rc_paint RECT
f_restore bool
f_incupdate bool
rgbreserved [32]byte
}
struct WNDCLASSEXW {
mut:
cb_size u32
style u32
lpfn_wnd_proc WndProc
cb_cls_extra int
cb_wnd_extra int
hinstance voidptr
hicon voidptr
hcursor voidptr
hbr_background voidptr
lpsz_menuname &u16 = voidptr(0)
lpsz_classname &u16 = voidptr(0)
hiconsm voidptr
}
struct MSG {
hwnd voidptr
message u32
wparam u64
lparam i64
time u32
pt voidptr
lprivate u32
}
const(
image_icon = 2
lr_defaultcolor = 0x00000000
lr_defaultsize = 0x00000040
lr_shared = 0x00008000
)
[callconv: stdcall]
fn wnd_proc(hwnd voidptr, message u32, wparam usize, lparam isize) isize {
match int(message) {
C.WM_COMMAND, C.WM_SYSCOMMAND {
id := loword(u64(wparam))
match int(id) {
C.ID_HELP_ABOUT {
show_about_dialog(hwnd)
return 0
}
C.ID_FILE_EXIT {
C.DestroyWindow(hwnd)
return 0
}
else {}
}
}
C.WM_DESTROY {
C.PostQuitMessage(0)
return 0
}
else {}
}
return C.DefWindowProcW(hwnd, message, wparam, lparam)
}
fn create_window(hinstance voidptr) {
mut wndclassex := WNDCLASSEXW{}
wndclassex.cb_size = sizeof(wndclassex)
wndclassex.style = u32(C.CS_HREDRAW | C.CS_VREDRAW)
wndclassex.lpfn_wnd_proc = WndProc(wnd_proc)
wndclassex.hinstance = hinstance
wndclassex.hicon = C.LoadImageW(hinstance,
C.MAKEINTRESOURCE(C.IDI_APPICON),
image_icon,
0,
0,
lr_defaultsize | lr_defaultcolor| lr_shared)
wndclassex.hicon = C.LoadIconW(0, C.MAKEINTRESOURCE(C.IDI_APPICON))
wndclassex.hcursor = C.LoadCursorW(0, C.MAKEINTRESOURCE(C.IDC_ARROW))
wndclassex.hbr_background = C.GetStockObject(C.WHITE_BRUSH)
wndclassex.lpsz_menuname = C.MAKEINTRESOURCE(C.IDR_MAINMENU)
wndclassex.lpsz_classname = app_name
wndclassex.hiconsm = C.LoadImageW(hinstance,
C.MAKEINTRESOURCE(C.IDI_APPICON),
image_icon,
16,
16,
lr_defaultsize | lr_defaultcolor| lr_shared)
atom := C.RegisterClassExW(&wndclassex)
if atom == 0 { return }
caption := "The Hello Program".to_wide()
hwnd := C.CreateWindowExW(0,
atom,
caption,
C.WS_OVERLAPPEDWINDOW,
C.CW_USEDEFAULT,
C.CW_USEDEFAULT,
400,
300,
0,
0,
hinstance,
0)
if hwnd == 0 { return }
h_sys_menu := C.GetSystemMenu(hwnd, false)
C.InsertMenuW(h_sys_menu, 5, C.MF_BYPOSITION | C.MF_SEPARATOR, 0, C.NULL)
C.InsertMenuW(h_sys_menu, 6, C.MF_BYPOSITION, C.ID_HELP_ABOUT, "About".to_wide())
accel := C.LoadAcceleratorsW(hinstance, C.MAKEINTRESOURCE(C.IDR_ACCELERATOR))
C.ShowWindow(hwnd, 1)
if !C.UpdateWindow(hwnd) { return }
msg := MSG{}
for {
ret := C.GetMessageW(&msg, 0, 0, 0)
if ret <= 0 {
break // end program
}
res := C.TranslateAcceleratorW(hwnd, accel, &msg)
if res == 0 {
C.TranslateMessage(&msg)
C.DispatchMessageW(&msg)
}
}
}
fn main() {
hinstance := C.GetModuleHandleW(voidptr(0))
mut icc := INITCOMMONCONTROLSEX {
dw_size: sizeof(INITCOMMONCONTROLSEX)
dw_icc: 0xFFFF
}
if !C.InitCommonControlsEx(&icc) {
C.MessageBoxW(0, '${C.CommDlgExtendedError()}'.to_wide(), 'InitCommonControlsEx ERROR'.to_wide(), 0)
}
create_window(hinstance)
}
#pragma once
#ifndef IDC_STATIC
#define IDC_STATIC (-1)
#endif
#define IDI_APPICON 101
#define IDR_MAINMENU 102
#define IDR_ACCELERATOR 103
#define IDD_ABOUTDIALOG 104
#define ID_FILE_EXIT 40001
#define ID_HELP_ABOUT 40002
#define IDI_HELLO 1001
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment