Hi,
I’m trying to rewrite the following code from
https://sjohannes.wordpress.com/2012/03/23/win32-python-getting-all-window-titles/
from Python to Julia
import ctypes
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
titles = []
def foreach_window(hwnd, lParam):
if IsWindowVisible(hwnd):
length = GetWindowTextLength(hwnd)
buff = ctypes.create_unicode_buffer(length + 1)
GetWindowText(hwnd, buff, length + 1)
titles.append(buff.value)
return True
EnumWindows(EnumWindowsProc(foreach_window), 0)
print(titles)
The code lists titles of all currently visible windows.
I’m struggling with how to specify the stdcall calling convention for the callback function. In a simple ccall one can specify the calling convention
tickCount = ccall( (:GetTickCount, "kernel32"), stdcall, UInt32, () )
but for callback, the function pointer created by cfunction has no calling convention property. Is such functionality available?
Cheers,
Petr
No, calling convention specification is not supported for cfunction. But calling conventions are unified on 64-bit Windows so this won’t matter unless you are on 32-bit Windows.
see also: stdcall with cfunction? · Issue #5613 · JuliaLang/julia · GitHub
@ihnorton Thank you for the explanation. Still my attempt crashes julia:
function foreach_window{T}(hwnd::T, lParam::T)
return convert(Cint, 1)::Cint
end
const windowEnumCallback = cfunction(foreach_window, Cint, (Ref{Cint}, Ref{Cint}))
ccall((:EnumWindows, "User32"), stdcall, Cint, (Ptr{Void}, Ptr{Cint}), windowEnumCallback, Ref{Cint}(0))
the signatures are
Enumerates all top-level windows on the screen by passing the handle to each window, in turn, to an application-defined callback function. EnumWindows continues until the last top-level window is enumerated or the callback function returns FALSE.
BOOL WINAPI EnumWindows(
_In_ WNDENUMPROC lpEnumFunc,
_In_ LPARAM lParam
);
BOOL CALLBACK EnumWindowsProc(
_In_ HWND hwnd,
_In_ LPARAM lParam
);
Please review the C interface section of the manual. There are a few problems, such as:
the cfunction signature must match the function declaration
Ref is Julia-owned memory, so it doesn’t make sense in the cfunction signature
foreach_window should not be parameterized by type ({T})
passing a Ref{Cint}(0) to EnumWindows doesn’t make sense – it’s just a long.
The code below works; hopefully enough to get you going:
typealias HANDLE Ptr{Void}
typealias LPARAM Clong
handles = HANDLE[]
function foreach_window(hwnd::HANDLE, lParam::LPARAM)
push!(handles, hwnd)
return convert(Cint, 1)::Cint
end
const windowEnumCallback = cfunction(foreach_window, Cint, (HANDLE, LPARAM))
ccall((:EnumWindows, "User32"), stdcall, Cint, (Ptr{Void}, LPARAM), windowEnumCallback, 0)
(I have some old demo code here that might be helpful – although I have no idea if it works at all in current Julia)
Works great, thank you Isaiah. Making clarification in manual.