windows working
This commit is contained in:
parent
70163d4e12
commit
69d7d0611e
|
@ -341,6 +341,7 @@ const WM_INITMENUPOPUP = @as(u32, 279);
|
|||
const WM_DRAWCLIPBOARD = @as(u32, 776);
|
||||
const WM_SIZECLIPBOARD = @as(u32, 779);
|
||||
const WM_CHANGECBCHAIN = @as(u32, 781);
|
||||
const WM_CLIPBOARDUPDATE = @as(u32, 797);
|
||||
|
||||
const WM_USER = @as(u32, 1024);
|
||||
// USER constants here - not part of Windows headers
|
||||
|
@ -492,6 +493,60 @@ extern "USER32" fn UpdateWindow(
|
|||
hWnd: ?w.HWND,
|
||||
) callconv(w.WINAPI) BOOL;
|
||||
|
||||
const REDRAW_WINDOW_FLAGS = enum(u32) {
|
||||
INVALIDATE = 1,
|
||||
INTERNALPAINT = 2,
|
||||
ERASE = 4,
|
||||
VALIDATE = 8,
|
||||
NOINTERNALPAINT = 16,
|
||||
NOERASE = 32,
|
||||
NOCHILDREN = 64,
|
||||
ALLCHILDREN = 128,
|
||||
UPDATENOW = 256,
|
||||
ERASENOW = 512,
|
||||
FRAME = 1024,
|
||||
NOFRAME = 2048,
|
||||
_,
|
||||
pub fn initFlags(o: struct {
|
||||
INVALIDATE: u1 = 0,
|
||||
INTERNALPAINT: u1 = 0,
|
||||
ERASE: u1 = 0,
|
||||
VALIDATE: u1 = 0,
|
||||
NOINTERNALPAINT: u1 = 0,
|
||||
NOERASE: u1 = 0,
|
||||
NOCHILDREN: u1 = 0,
|
||||
ALLCHILDREN: u1 = 0,
|
||||
UPDATENOW: u1 = 0,
|
||||
ERASENOW: u1 = 0,
|
||||
FRAME: u1 = 0,
|
||||
NOFRAME: u1 = 0,
|
||||
}) REDRAW_WINDOW_FLAGS {
|
||||
return @intToEnum(REDRAW_WINDOW_FLAGS, (if (o.INVALIDATE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.INVALIDATE) else 0) | (if (o.INTERNALPAINT == 1) @enumToInt(REDRAW_WINDOW_FLAGS.INTERNALPAINT) else 0) | (if (o.ERASE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.ERASE) else 0) | (if (o.VALIDATE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.VALIDATE) else 0) | (if (o.NOINTERNALPAINT == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOINTERNALPAINT) else 0) | (if (o.NOERASE == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOERASE) else 0) | (if (o.NOCHILDREN == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOCHILDREN) else 0) | (if (o.ALLCHILDREN == 1) @enumToInt(REDRAW_WINDOW_FLAGS.ALLCHILDREN) else 0) | (if (o.UPDATENOW == 1) @enumToInt(REDRAW_WINDOW_FLAGS.UPDATENOW) else 0) | (if (o.ERASENOW == 1) @enumToInt(REDRAW_WINDOW_FLAGS.ERASENOW) else 0) | (if (o.FRAME == 1) @enumToInt(REDRAW_WINDOW_FLAGS.FRAME) else 0) | (if (o.NOFRAME == 1) @enumToInt(REDRAW_WINDOW_FLAGS.NOFRAME) else 0));
|
||||
}
|
||||
};
|
||||
const RDW_INVALIDATE = REDRAW_WINDOW_FLAGS.INVALIDATE;
|
||||
const RDW_INTERNALPAINT = REDRAW_WINDOW_FLAGS.INTERNALPAINT;
|
||||
const RDW_ERASE = REDRAW_WINDOW_FLAGS.ERASE;
|
||||
const RDW_VALIDATE = REDRAW_WINDOW_FLAGS.VALIDATE;
|
||||
const RDW_NOINTERNALPAINT = REDRAW_WINDOW_FLAGS.NOINTERNALPAINT;
|
||||
const RDW_NOERASE = REDRAW_WINDOW_FLAGS.NOERASE;
|
||||
const RDW_NOCHILDREN = REDRAW_WINDOW_FLAGS.NOCHILDREN;
|
||||
const RDW_ALLCHILDREN = REDRAW_WINDOW_FLAGS.ALLCHILDREN;
|
||||
const RDW_UPDATENOW = REDRAW_WINDOW_FLAGS.UPDATENOW;
|
||||
const RDW_ERASENOW = REDRAW_WINDOW_FLAGS.ERASENOW;
|
||||
const RDW_FRAME = REDRAW_WINDOW_FLAGS.FRAME;
|
||||
const RDW_NOFRAME = REDRAW_WINDOW_FLAGS.NOFRAME;
|
||||
|
||||
const HGDIOBJ = *opaque {};
|
||||
const HRGN = HGDIOBJ;
|
||||
|
||||
extern "USER32" fn RedrawWindow(
|
||||
hWnd: ?w.HWND,
|
||||
lprcUpdate: ?*const RECT,
|
||||
hrgnUpdate: ?HRGN,
|
||||
flags: REDRAW_WINDOW_FLAGS,
|
||||
) callconv(w.WINAPI) BOOL;
|
||||
|
||||
// Data exchange
|
||||
extern "USER32" fn GetClipboardData(
|
||||
uFormat: u32,
|
||||
|
@ -499,19 +554,19 @@ extern "USER32" fn GetClipboardData(
|
|||
|
||||
extern "USER32" fn GetClipboardOwner() callconv(w.WINAPI) ?w.HWND;
|
||||
|
||||
extern "USER32" fn SetClipboardViewer(
|
||||
hWndNewViewer: ?w.HWND,
|
||||
) callconv(w.WINAPI) ?w.HWND;
|
||||
|
||||
extern "USER32" fn OpenClipboard(
|
||||
hWndNewOwner: ?w.HWND,
|
||||
) callconv(w.WINAPI) BOOL;
|
||||
|
||||
extern "USER32" fn CloseClipboard() callconv(w.WINAPI) BOOL;
|
||||
|
||||
extern "USER32" fn ChangeClipboardChain(
|
||||
hWndRemove: ?w.HWND,
|
||||
hWndNewNext: ?w.HWND,
|
||||
extern "USER32" fn AddClipboardFormatListener(
|
||||
hwnd: ?w.HWND,
|
||||
) callconv(w.WINAPI) BOOL;
|
||||
|
||||
// TODO: this type is limited to platform 'windows6.0.6000'
|
||||
extern "USER32" fn RemoveClipboardFormatListener(
|
||||
hwnd: ?w.HWND,
|
||||
) callconv(w.WINAPI) BOOL;
|
||||
|
||||
extern "USER32" fn GetPriorityClipboardFormat(
|
||||
|
@ -833,14 +888,29 @@ fn getWinStyleString(comptime buflen: u32, str: []const u8) [buflen]u8 {
|
|||
return buf;
|
||||
}
|
||||
|
||||
// Globals
|
||||
var uFormat: w.UINT = @enumToInt(CF_TEXT);
|
||||
var fAuto: w.BOOL = w.TRUE;
|
||||
var icon_data: NOTIFYICONDATAA = undefined;
|
||||
var window_state: union(enum(u8)) {
|
||||
INITIAL = 0,
|
||||
NORMAL = 1,
|
||||
MINIMIZED = 2,
|
||||
} = .INITIAL;
|
||||
var gpa: std.heap.GeneralPurposeAllocator(.{}) = undefined;
|
||||
var contents: [:0]const u8 = "";
|
||||
var free_contents = false;
|
||||
|
||||
pub export fn wWinMain(hInstance: w.HINSTANCE, hPrevInstance: ?w.HINSTANCE, lpCmdLine: w.PWSTR, nCmdShow: w.INT) w.INT {
|
||||
_ = hPrevInstance;
|
||||
_ = lpCmdLine;
|
||||
_ = nCmdShow;
|
||||
|
||||
gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
|
||||
h_instance = hInstance;
|
||||
|
||||
dbg_msg = getWinStyleString(17, "TODO: Send now: x");
|
||||
// Register the window class.
|
||||
var wc: WNDCLASSA = .{
|
||||
.lpszClassName = "Clipboard watcher",
|
||||
|
@ -903,33 +973,8 @@ pub export fn wWinMain(hInstance: w.HINSTANCE, hPrevInstance: ?w.HINSTANCE, lpCm
|
|||
return 0;
|
||||
}
|
||||
|
||||
// Globals
|
||||
var uFormat: w.UINT = @bitReverse(c_uint, 0);
|
||||
var fAuto: w.BOOL = w.TRUE;
|
||||
var hwndNextViewer: ?w.HWND = null;
|
||||
var icon_data: NOTIFYICONDATAA = undefined;
|
||||
var dbg_msg: [17]u8 = undefined;
|
||||
var cnt: u8 = 0;
|
||||
var window_state: union(enum(u8)) {
|
||||
INITIAL = 0,
|
||||
NORMAL = 1,
|
||||
MINIMIZED = 2,
|
||||
} = .INITIAL;
|
||||
|
||||
fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) callconv(w.WINAPI) w.LRESULT { //APIENTRY {
|
||||
// static HWND hwndNextViewer;
|
||||
//
|
||||
// HDC hdc;
|
||||
// HDC hdcMem;
|
||||
// PAINTSTRUCT ps;
|
||||
// LPPAINTSTRUCT lpps;
|
||||
// RECT rc;
|
||||
// LPRECT lprc;
|
||||
// HGLOBAL hglb;
|
||||
// LPSTR lpstr;
|
||||
// HBITMAP hbm;
|
||||
// HENHMETAFILE hemf;
|
||||
// HWND hwndOwner;
|
||||
const allocator = &gpa.allocator;
|
||||
|
||||
switch (uMsg) {
|
||||
WM_PAINT => {
|
||||
|
@ -989,21 +1034,9 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
// }
|
||||
},
|
||||
@enumToInt(CF_TEXT) => {
|
||||
if (OpenClipboard(hwnd) > 0) {
|
||||
var hglb = GetClipboardData(uFormat).?;
|
||||
const hnd = @intCast(isize, @ptrToInt(hglb));
|
||||
var lpstr = GlobalLock(hnd).?;
|
||||
|
||||
_ = GetClientRect(hwnd, &rc);
|
||||
// TODO: copy our lpstr and ship it to our common handler
|
||||
cnt = (cnt + 1) % 10;
|
||||
dbg_msg[dbg_msg.len - 1] = '0' + cnt;
|
||||
_ = MessageBoxA(hwnd, @ptrCast([*:0]const u8, &dbg_msg), "Debug", 0);
|
||||
_ = DrawTextA(hdc, @ptrCast([*:0]const u8, lpstr), -1, &rc, DT_LEFT);
|
||||
|
||||
_ = GlobalUnlock(hnd);
|
||||
_ = CloseClipboard();
|
||||
}
|
||||
_ = DrawTextA(hdc, contents, -1, &rc, DT_LEFT);
|
||||
},
|
||||
|
||||
@enumToInt(CF_ENHMETAFILE) => {
|
||||
|
@ -1043,6 +1076,7 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
},
|
||||
WM_SIZE => {
|
||||
if (uFormat == @enumToInt(CF_OWNERDISPLAY)) {
|
||||
// I don't believe this will ever execute and can be removed
|
||||
var hwndOwner = GetClipboardOwner().?;
|
||||
var hglb = GlobalAlloc(GMEM_MOVEABLE, @sizeOf(RECT));
|
||||
defer _ = GlobalFree(hglb);
|
||||
|
@ -1054,11 +1088,35 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
_ = SendMessageA(hwndOwner, WM_SIZECLIPBOARD, @ptrToInt(hwnd), hglb);
|
||||
}
|
||||
},
|
||||
WM_CLIPBOARDUPDATE => { // Message arrives only after AddClipboardFormatListener
|
||||
|
||||
// Get a lock on the clipboard
|
||||
if (OpenClipboard(hwnd) > 0) {
|
||||
defer _ = CloseClipboard();
|
||||
var hglb = GetClipboardData(uFormat).?;
|
||||
const hnd = @intCast(isize, @ptrToInt(hglb));
|
||||
var lpstr = GlobalLock(hnd).?;
|
||||
defer _ = GlobalUnlock(hnd);
|
||||
|
||||
if (free_contents) {
|
||||
allocator.free(contents);
|
||||
}
|
||||
free_contents = true;
|
||||
contents = std.fmt.allocPrintZ(allocator, "{s}", .{@ptrCast([*:0]const u8, lpstr)}) catch blk: {
|
||||
_ = MessageBoxA(hwnd, "Allocation failed copying clipboard contents", "Error", 0);
|
||||
free_contents = false;
|
||||
break :blk "";
|
||||
};
|
||||
}
|
||||
if (RedrawWindow(hwnd, null, null, RDW_INVALIDATE) != w.TRUE) {
|
||||
_ = MessageBoxA(hwnd, "Redraw failed", "Error", 0);
|
||||
}
|
||||
},
|
||||
WM_CREATE => {
|
||||
|
||||
// Add the window to the clipboard viewer chain.
|
||||
|
||||
hwndNextViewer = SetClipboardViewer(hwnd);
|
||||
if (AddClipboardFormatListener(hwnd) != w.TRUE) {
|
||||
_ = MessageBoxA(hwnd, "Could not add clipboard listener", "Error", 0);
|
||||
return -1; // oops
|
||||
}
|
||||
var tip = getWinStyleString(128, "Clipboard processor");
|
||||
icon_data = .{
|
||||
.cbSize = @sizeOf(@TypeOf(icon_data)),
|
||||
|
@ -1081,8 +1139,7 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
.guidItem = Guid.initString("3e781b84-3ffd-44a1-b3ab-11d0f90136f9"), // generated from duckduckgo
|
||||
.hBalloonIcon = null,
|
||||
};
|
||||
// stData.hIcon = g_hIcon = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_TRAYICON));
|
||||
// LoadStringSafe(IDS_TIP, stData.szTip, _countof(stData.szTip));
|
||||
|
||||
if (Shell_NotifyIconA(NIM_ADD, &icon_data) != w.TRUE) {
|
||||
_ = MessageBoxA(hwnd, "Notification Icon failed to create", "Error", 0);
|
||||
return -1; // oops
|
||||
|
@ -1110,50 +1167,15 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
else => {},
|
||||
}
|
||||
},
|
||||
WM_CHANGECBCHAIN => {
|
||||
|
||||
// If the next window is closing, repair the chain.
|
||||
|
||||
// if ((HWND) wParam == hwndNextViewer)
|
||||
if (wParam == @ptrToInt(hwndNextViewer.?)) {
|
||||
hwndNextViewer = @intToPtr(w.HWND, @intCast(usize, lParam)); // just a cast
|
||||
|
||||
// Otherwise, pass the message to the next link.
|
||||
|
||||
} else if (hwndNextViewer) |hnv| {
|
||||
_ = SendMessageA(hnv, uMsg, wParam, lParam);
|
||||
}
|
||||
},
|
||||
|
||||
WM_DESTROY => {
|
||||
_ = ChangeClipboardChain(hwnd, hwndNextViewer);
|
||||
_ = RemoveClipboardFormatListener(hwnd);
|
||||
_ = Shell_NotifyIconA(NIM_DELETE, &icon_data);
|
||||
PostQuitMessage(0);
|
||||
},
|
||||
|
||||
WM_DRAWCLIPBOARD => { // clipboard contents changed.
|
||||
|
||||
// Update the window by using Auto clipboard format.
|
||||
|
||||
SetAutoView(hwnd);
|
||||
|
||||
// Pass the message to the next window in clipboard
|
||||
// viewer chain.
|
||||
|
||||
_ = SendMessageA(hwndNextViewer, uMsg, wParam, lParam);
|
||||
},
|
||||
|
||||
WM_INITMENUPOPUP => {
|
||||
// if (!HIWORD(lParam))
|
||||
// if (lParam > 0xffffffff)
|
||||
// InitMenu(hwnd, wParam); // (HMENU) wParam);
|
||||
},
|
||||
|
||||
WM_COMMAND => {
|
||||
// switch (LOWORD(wParam)) {
|
||||
switch (wParam & 0xffffffff) {
|
||||
IDM_EXIT => _ = DestroyWindow(hwnd),
|
||||
// IDM_AUTO => SetAutoView(hwnd),
|
||||
else => {
|
||||
fAuto = w.FALSE;
|
||||
uFormat = @intCast(w.UINT, wParam & 0xffffffff); // LOWORD(wParam);
|
||||
|
@ -1165,103 +1187,3 @@ fn MainWndProc(hwnd: w.HWND, uMsg: u32, wParam: w.WPARAM, lParam: w.LPARAM) call
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
var auPriorityList: [4]u32 = .{
|
||||
@enumToInt(CF_OWNERDISPLAY),
|
||||
@enumToInt(CF_TEXT),
|
||||
@enumToInt(CF_ENHMETAFILE),
|
||||
@enumToInt(CF_BITMAP),
|
||||
};
|
||||
|
||||
fn SetAutoView(hwnd: w.HWND) callconv(w.WINAPI) void {
|
||||
var runtime_zero: usize = 0;
|
||||
var auPriorityListSlice = auPriorityList[runtime_zero..auPriorityList.len];
|
||||
uFormat = @intCast(c_uint, GetPriorityClipboardFormat(auPriorityListSlice.ptr, 4));
|
||||
fAuto = w.TRUE;
|
||||
|
||||
_ = InvalidateRect(hwnd, null, w.TRUE);
|
||||
_ = UpdateWindow(hwnd);
|
||||
}
|
||||
|
||||
// fn InitMenu(hwnd: w.HWND, hmenu: w.HMENU) callconv(w.WINAPI) void {
|
||||
// // UINT uFormat;
|
||||
// // char szFormatName[80];
|
||||
// // LPCSTR lpFormatName;
|
||||
// // UINT fuFlags;
|
||||
// // UINT idMenuItem;
|
||||
//
|
||||
// // If a menu is not the display menu, no initialization is necessary.
|
||||
//
|
||||
// if (GetMenuItemID(hmenu, 0) != IDM_AUTO)
|
||||
// return;
|
||||
//
|
||||
// // Delete all menu items except the first.
|
||||
//
|
||||
// while (GetMenuItemCount(hmenu) > 1)
|
||||
// DeleteMenu(hmenu, 1, MF_BYPOSITION);
|
||||
//
|
||||
// // Check or uncheck the Auto menu item.
|
||||
//
|
||||
// if (fAuto) {
|
||||
// fuFlags = MF_BYCOMMAND | MF_CHECKED;
|
||||
// } else fuFlags = MF_BYCOMMAND | MF_UNCHECKED;
|
||||
//
|
||||
// CheckMenuItem(hmenu, IDM_AUTO, fuFlags);
|
||||
//
|
||||
// // If there are no clipboard formats, return.
|
||||
//
|
||||
// if (CountClipboardFormats() == 0)
|
||||
// return;
|
||||
//
|
||||
// // Open the clipboard.
|
||||
//
|
||||
// if (!OpenClipboard(hwnd))
|
||||
// return;
|
||||
//
|
||||
// // Add a separator and then a menu item for each format.
|
||||
//
|
||||
// AppendMenu(hmenu, MF_SEPARATOR, 0, null);
|
||||
// var uFormat = EnumClipboardFormats(0);
|
||||
//
|
||||
// while (uFormat) {
|
||||
// // Call an application-defined function to get the name
|
||||
// // of the clipboard format.
|
||||
//
|
||||
// var lpFormatName = GetPredefinedClipboardFormatName(uFormat);
|
||||
//
|
||||
// // For registered formats, get the registered name.
|
||||
//
|
||||
// if (lpFormatName == null) {
|
||||
//
|
||||
// // Note that, if the format name is larger than the
|
||||
// // buffer, it is truncated.
|
||||
// if (GetClipboardFormatName(uFormat, szFormatName, @sizeOf(szFormatName))) {
|
||||
// lpFormatName = szFormatName;
|
||||
// } else lpFormatName = "(unknown)";
|
||||
// }
|
||||
//
|
||||
// // Add a menu item for the format. For displayable
|
||||
// // formats, use the format ID for the menu ID.
|
||||
//
|
||||
// if (IsDisplayableFormat(uFormat)) {
|
||||
// fuFlags = MF_STRING;
|
||||
// idMenuItem = uFormat;
|
||||
// } else {
|
||||
// fuFlags = MF_STRING | MF_GRAYED;
|
||||
// idMenuItem = 0;
|
||||
// }
|
||||
// AppendMenu(hmenu, fuFlags, idMenuItem, lpFormatName);
|
||||
//
|
||||
// uFormat = EnumClipboardFormats(uFormat);
|
||||
// }
|
||||
// CloseClipboard();
|
||||
// }
|
||||
//
|
||||
// fn IsDisplayableFormat(ufmt: w.UINT) callconv(w.WINAPI) w.BOOL {
|
||||
// switch (ufmt) {
|
||||
// CF_OWNERDISPLAY => return true,
|
||||
// CF_TEXT => return true,
|
||||
// CF_ENHMETAFILE => return true,
|
||||
// CF_BITMAP => return true,
|
||||
// else => return false,
|
||||
// }
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue
Block a user