【发布时间】:2012-06-18 01:07:52
【问题描述】:
我有以下代码,如果我提供无效参数(虽然,显然不起作用),但只要我提供准确的参数,ruby segfaults。我倾向于认为这是我的代码和/或 ruby 实际调用此 API 函数的能力的问题,但我想要更多输入。我已经尝试过Win32API 和DL::Importer,结果相同。有什么办法可以让它工作吗?
对于好奇的there's full background available here,包括在不同分支上尝试使用Win32API 和DL::Importer。在这两种情况下,您都在寻找examples/windows-test。
编辑:我已经设法让RegisterClassEx 工作,但这仍然没有帮助。 Ruby 在CreateWindowEx 中默默地崩溃。
下面的输出如下:
wndproc:4293787656
实例:4194304
进入 RegisterClassEx
窗口等级:49795
进入 CreateWindowEx
编辑 2:我正在编写的代码有点大,需要将其全部粘贴到 SE 中。如果你想要所有的背景,你可以在上面的链接中看到它。不过,我已尝试保留此处包含的所有相关内容。
class Windows
def initialize
puts "wndproc: #{Win32::User32::WNDPROC}"
hInstance = Win32::Kernel32::GetModuleHandle(DL::NULL)
puts "hInstance: #{hInstance}"
puts "Entering RegisterClassEx"
@window_class_struct = Win32::User32::WNDCLASSEX.malloc
@window_class_struct.cbSize = Win32::User32::WNDCLASSEX.size
@window_class_struct.style = Win32::User32::CS_HREDRAW | Win32::User32::CS_VREDRAW
@window_class_struct.lpfnWndProc = Win32::User32::WNDPROC
@window_class_struct.cbClsExtra = 0
@window_class_struct.cbWndExtra = 0
@window_class_struct.hInstance = hInstance
@window_class_struct.hIcon = 0
@window_class_struct.hCursor = 0
@window_class_struct.hbrBackground = Win32::User32::COLOR_WINDOWFRAME
@window_class_struct.lpszMenuName = DL::NULL
@window_class_struct.lpszClassName = 'ruby-skype'
@window_class_struct.hIconSm = 0
p @window_class_struct
@window_class = Win32::User32::RegisterClassEx(@window_class_struct.to_i)
puts "Window Class: #{@window_class}"
puts "Entering CreateWindowEx"
@window = Win32::User32::CreateWindowEx(0, 'ruby-skype', 'ruby-skype', Win32::User32::WS_OVERLAPPEDWINDOW,
0, 0, 200, 200, DL::NULL, DL::NULL, DL::NULL)
puts "Exited CreateWindowEx"
p @window
end
module Win32
module Types
def included(m)
m.module_eval {
include ::DL::Win32Types
# @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx
typealias('HBRUSH', 'HANDLE')
typealias('HCURSOR', 'HANDLE')
typealias('HICON', 'HANDLE')
typealias('HMENU', 'HANDLE')
typealias('HMODULE', 'HANDLE')
typealias('LPCTSTR', 'unsigned char *')
typealias('LPVOID', 'void *')
typealias('WNDPROC', 'void *') # Actually a function pointer
typealias('WNDCLASSEX', 'void *') # struct
}
end
module_function :included
end
module User32
extend DL
extend DL::Importer
dlload 'user32'
include Types
extern 'HWND CreateWindowEx(DWORD, LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE)'
WNDPROC = set_callback DL::TYPE_LONG, 4 do |window_handle, message_id, wParam, lParam|
puts "WM: #{message_id}"
end
end
end
end
Windows.new
【问题讨论】:
-
好吧,你告诉窗口不要创建窗口。 CreateWindowEx 的第二个参数是要创建的窗口的类名。对于预定义控件(Windows),这可能是 BUTTON、EDIT 等...如果要创建父窗口,则需要先使用 RegisterWindowEx 创建一个原子,然后将其作为类名传递
-
@Gunner:这将是我今晚的第一次尝试,但如果是这样,那么为什么类名在 API 文档中显示为可选字段?
-
因为我们在讨论 MS 的文档编写器,他们似乎犯了很多错误/遗漏。无论如何,您应该检查 API 调用的返回。 CreateWindowEx 出错时返回 NULL,出错时调用 GetLastError 获取原因
-
@Gunner:我从 GetLastError 或段错误中得到 NULL/Invalid Argument,因此我的问题在这里。我假设段错误意味着我正在取得进展并传递了正确的参数,除了 Ruby 和/或 Win32 API 不喜欢另一个并且一切都失败了。
-
@Gunner:查看更新。我让 RegisterClassEx 工作了,但还是不行 :( 我试图尽可能地遵循这封信:msdn.microsoft.com/en-us/library/bb384843.aspx
标签: ruby winapi createwindowex