Quantcast
Channel: Active questions tagged ruby - Stack Overflow
Viewing all articles
Browse latest Browse all 4612

How can I correctly use the FFI Ruby library to build a simple Window by using Win32 APIs?

$
0
0

I've been trying to use Ruby's FFI to make a project that needs Win32 APIs. I can't get to see the Window at all. I get MessageBox to run successfully but no luck making an empty Window. My guess is that the issue lies within wrong types some variables more specifically WindowProc callback.

Here's the code:

require 'ffi'module Win32  NULL = 0  NO_ERROR = 1  ERROR_SUCCESS = 0x00  ERROR_NOT_LOCKED = 0x9E  ERROR_CLIPBOARD_NOT_OPEN = 0x58A  extend FFI::Library  class WNDCLASS < FFI::Struct    layout :style, :uint,            :lpfnWndProc, :pointer,           :cbClsExtra, :int,            :cbWndExtra, :int,            :hInstance, :pointer,            :hIcon, :pointer,            :hCursor, :pointer,           :hbrBackground, :pointer,           :lpszMenuName, :pointer,            :lpszClassName, :pointer  end  class WNDCLASSW < FFI::Struct    layout :style, :uint,            :lpfnWndProc, :pointer,           :cbClsExtra, :int,            :cbWndExtra, :int,            :hInstance, :pointer,            :hIcon, :pointer,            :hCursor, :pointer,           :hbrBackground, :pointer,           :lpszMenuName, :pointer,            :lpszClassName, :pointer  end  class WNDCLASSEX < FFI::Struct    layout :cbSize, :uint,           :style, :uint,          :lpfnWndProc, :pointer,          :cbClsExtra, :int,          :cbWndExtra, :int,           :hInstance, :pointer,          :hIcon, :pointer,           :hIconSm, :pointer,           :hCursor, :pointer,           :hbrBackground, :pointer,           :lpszMenuName, :pointer,           :lpszClassName, :pointer  end  class MSG < FFI::Struct    layout :hwnd, :uint,     :message, :uint,     :wparam, :pointer,     :lparam, :pointer,     :time, :uint,     :pt_x, :int,     :pt_y, :int  end  module Kernel32    extend FFI::Library    ffi_lib 'Kernel32'    ffi_convention :stdcall    attach_function :GetModuleHandleW, [ :int ], :pointer  end  module User32    extend FFI::Library    ffi_lib 'User32'    ffi_convention :stdcall    # MessageBox(HWND, LPCTSTR, LPCTSTR, uint)    attach_function :MessageBoxW, [:pointer, :buffer_in, :buffer_in, :uint], :int    # HWND CreateWindowExW(DWORD, LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID);    attach_function :CreateWindowExW, [:int, :buffer_in, :buffer_in, :int, :int, :int, :int, :int, :pointer, :pointer, :pointer, :pointer], :pointer    # extern 'ATOM RegisterClass(const WINDCLASS*);' Not Done    # extern 'ATOM RegisterClassW(const WINDCLASS*);'    attach_function :RegisterClassW, [:pointer], :ushort    #extern 'ATOM RegisterClassEx(const WINDCLASSEX*);'    #bool UpdateWindow(HWND)    attach_function :UpdateWindow, [:pointer], :bool    #'bool ShowWindow(HWND, int);'    attach_function :ShowWindow, [:pointer, :int], :bool    # bool GetMessage(void*, HWND, uint, uint);'    attach_function :GetMessageW, [:pointer, :pointer, :uint, :uint], :bool    # bool TranslateMessage(const void*)    attach_function :TranslateMessage, [:pointer], :bool    # bool DispatchMessage(const void*)    attach_function :DispatchMessageW, [:pointer], :long    # bool PostQuitMessage(uint)    attach_function :PostQuitMessage, [:uint], :bool    #void* DefWindowProcW(HWND, void*, void*, void*)    attach_function :DefWindowProcW, [:pointer, :pointer, :pointer, :pointer], :pointer    # HCURSOR LoadCursor(HINSTANCE, LPCTSTR)    attach_function :LoadCursorW, [:pointer, :int], :pointer    attach_function :WindowProcedure, [:pointer, :uint, :pointer, :pointer], :long    Callback = FFI::Function.new(:long, [:pointer, :uint, :uintptr_t, :uintptr_t]) do |hwnd, msg, w_param, l_param|        case msg        when 0x0001          p 'Window created'        when 0x0002          Win32::User32::PostQuitMessage(0)        else          Win32::User32::DefWindowProcW(hwnd, msg, w_param, l_param)        end    endendwc = Win32::WNDCLASS.newwclass_name = 'WindowClass'.encode('UTF-8')wc[:lpszClassName] = FFI::Pointer.new(wclass_name.to_i)wc[:hCursor] = Win32::User32::LoadCursorW(nil, 32512)wc[:hbrBackground] = 5wc[:hIcon] = 0wc[:cbClsExtra] = 0wc[:cbWndExtra] = 0wc[:hInstance] = Win32::Kernel32::GetModuleHandleW(0)wc[:style] = 0wc[:lpfnWndProc] = Win32::User32::WindowProcedure(Win32::User32::Callback)p Win32::User32::RegisterClassW(wc.pointer)wname = 'VentanaName'.encode('UTF-8')hwMain = Win32::User32::CreateWindowExW(0, FFI::Pointer.new(wclass_name.to_i), FFI::Pointer.new(wname.to_i), 0x10CF0000, 0, 0, 500, 500, nil, nil, nil, nil)if hwMain.nil?  raise StandardError.new 'Unable to create a Window'endmsg = Win32::MSG.newmsg_ptr = msg.to_ptrWin32::User32::ShowWindow(hwMain, 5)Win32::User32::UpdateWindow(hwMain)while true  m = Win32::User32::GetMessageW(msg_ptr, hwMain, 0, 0)  p m  if m != 0    Win32::User32::TranslateMessageW(msg_ptr)    Win32::User32::DispatchMessageW(msg_ptr)  else    break  endend

I initially used Fiddle, but lack of docs made it hard to stop guessing and look for AI help. After I switched to FFI I still had the same issue of the Window not showing up. I've read MS WinAPI docs and FFI examples.


Viewing all articles
Browse latest Browse all 4612

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>