Skip to content

Instantly share code, notes, and snippets.

@codehz
Created September 29, 2020 12:53
Show Gist options
  • Save codehz/516c2f1b6a03cde898a34faab54cf524 to your computer and use it in GitHub Desktop.
Save codehz/516c2f1b6a03cde898a34faab54cf524 to your computer and use it in GitHub Desktop.
const std = @import("std");
pub const HWND = *@Type(.Opaque);
pub const HICON = *@Type(.Opaque);
const INSTANCE = @Type(.Opaque);
pub const HINSTANCE = *const INSTANCE;
pub const PCWSTR = [*:0]align(1) const u16;
pub const HRESULT = u64;
extern "comctl32" fn TaskDialogIndirect(
config: *const TaskDialogConfig,
btn: ?*c_uint,
radio: ?*c_uint,
verified: ?*bool,
) callconv(.C) HRESULT;
extern "comctl32" fn TaskDialog(
hwnd: ?HWND,
inst: HINSTANCE,
title: PCWSTR,
instrustion: PCWSTR,
content: PCWSTR,
combtns: c_uint,
icns: PCWSTR, // -3
btn: ?*c_int,
) callconv(.C) HRESULT;
extern "comctl32" fn InitCommonControls() callconv(.C) void;
extern "user32" fn SetProcessDPIAware() callconv(.C) void;
extern "user32" fn LoadIconW(instance: ?HINSTANCE, name: PCWSTR) callconv(.C) ?HICON;
fn MAKEINTRESOURCE(id: i16) PCWSTR {
return std.meta.cast(PCWSTR, @intCast(usize, @bitCast(u16, id)));
}
extern const __ImageBase: INSTANCE;
pub fn Instance() HINSTANCE {
return &__ImageBase;
}
pub const L = std.unicode.utf8ToUtf16LeStringLiteral;
pub const isWindows = std.builtin.os.tag == .windows;
pub fn init() void {
SetProcessDPIAware();
InitCommonControls();
}
fn wecast(from: anytype) c_int {
const mid = std.meta.Int(false, @bitSizeOf(@TypeOf(from)));
return @intCast(c_int, @bitCast(mid, from));
}
const TaskDialogFlags = packed struct {
enable_hyperlinks: bool = false,
use_hicon_main: bool = false,
use_hicon_footer: bool = false,
allow_dialog_cancellation: bool = false,
use_command_links: bool = false,
use_command_links_icon: bool = false,
expand_footer_area: bool = false,
expanded_by_default: bool = false,
verification_flag_checked: bool = false,
show_progress_bar: bool = false,
show_marquee_progress_bar: bool = false,
callback_timer: bool = false,
position_relative_to_window: bool = false,
rtl_layout: bool = false,
no_default_radio_button: bool = false,
can_be_minimized: bool = false,
fn into(self: @This()) c_int {
return wecast(self);
}
};
const TaskDialogCommonButtonFlags = packed struct {
ok: bool = false,
yes: bool = false,
no: bool = false,
cancel: bool = false,
retry: bool = false,
close: bool = false,
fn into(self: @This()) c_int {
return wecast(self);
}
};
const IconUnion = extern union {
hicon: HICON,
res: PCWSTR,
};
const TaskDialogButton = packed struct {
id: c_int,
text: PCWSTR,
};
const TaskDialogCallback = fn (
hwnd: HWND,
msg: c_uint,
win: usize,
user: usize,
ref: ?*c_void,
) callconv(.C) HRESULT;
const TaskDialogConfig = packed struct {
size: c_uint = @sizeOf(TaskDialogConfig),
hwnd: ?HWND = null,
inst: HINSTANCE,
flags: c_int = 0,
btnflags: c_int = 0,
title: PCWSTR,
mainIcon: IconUnion,
instrustion: PCWSTR,
content: PCWSTR,
btnc: c_uint = 0,
btns: ?[*]TaskDialogButton = null,
btnd: c_uint = 0,
radioc: c_uint = 0,
radios: ?[*]TaskDialogButton = null,
radiod: c_uint = 0,
verification: ?PCWSTR = null,
expandedInfo: ?PCWSTR = null,
expandedCtl: ?PCWSTR = null,
collapsedCtl: ?PCWSTR = null,
footerIcon: IconUnion,
footer: ?PCWSTR = null,
callback: ?TaskDialogCallback = null,
callbackData: ?*c_void = null,
width: c_uint = 0,
};
pub fn showBox(title: PCWSTR, instrustion: PCWSTR, content: PCWSTR, cmd: PCWSTR, footer: PCWSTR) !void {
const cfg = TaskDialogConfig{
.flags = TaskDialogFlags.into(.{
.enable_hyperlinks = true,
.use_command_links = true,
.can_be_minimized = true,
}),
.btnflags = TaskDialogCommonButtonFlags.into(.{}),
.inst = Instance(),
.title = title,
.instrustion = instrustion,
.content = content,
.footer = footer,
.btnc = 1,
.btns = &[_]TaskDialogButton{.{
.id = 101,
.text = cmd,
}},
.mainIcon = .{ .res = L("WIFI") },
.footerIcon = .{ .res = MAKEINTRESOURCE(-3) },
};
const res = TaskDialogIndirect(&cfg, null, null, null);
switch (res) {
0 => return,
0x8007000E => return error.OutOfMemory,
0x80070057 => return error.InvalidArguments,
0x80004005 => return error.UnspecifiedFailure,
else => return error.UnexpectedError,
}
}
pub fn showError(title: PCWSTR, instrustion: PCWSTR, content: PCWSTR) !void {
const res = TaskDialog(null, Instance(), title, instrustion, content, 1, MAKEINTRESOURCE(-2), null);
switch (res) {
0 => return,
0x8007000E => return error.OutOfMemory,
0x80070057 => return error.InvalidArguments,
0x80004005 => return error.UnspecifiedFailure,
else => return error.UnexpectedError,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment