2

I know the following:

  • 'L' - Long
  • 'P' - Pointer
  • 'I' - Integer
  • 'V' - Void

My problem is that I can't pass a null pointer when I perform an API call. E.g.: ['L', 'P', 'L'] -> api.call(0, nil, 0) :: ArgumentError: Null pointer given. My question is: Are there more parameter types that I don't know about and what should I do to pass a null pointer as a method parameter?

Background

I have been searching the internet for native Ruby programming examples of WinForms-based applications. I have considered the .NET addition to Ruby known as IronRuby for simplicity in coding (trying to avoid wxRuby, and also a .NET fan), but I first want to be able to code explicitly in pure Ruby first.

Now, I have successfully been able to implement most addresses I've tested in the user32.dll object such as:

api = Win32API.new('user32', 'MessageBox', ['L', 'P', 'P', 'L'], 'I')
# or
api = Win32API.new('user32', 'MessageBeep', ['L'], 'I')

..but I cannot perform a CreateWindow Or CreateWindowEx without null parameters. If it would be of any help, I have found how to do this in Python here (under WinAPI).

Using Win32API: msdn.microsoft.com/en-us/library/ff381397(v=VS.85).aspx

[EDIT]
Well, I think I may have just solved my own problem with this link (warning: may contain inappropriate content): [link]

I more used that forum as reference and did a bit of fiddling around my self:
createwindow = Win32API.new("user32","CreateWindowEx",'lpplllllllll','l')
showwindow = Win32API.new('user32','ShowWindow',%w(l l),'l')

hWND = createwindow.call((0x00000100|0x00000200),"static", "Window Title",((0x4000000|0x80000000|0)|0x02000000),0,0,600,400,0,0,0,0)
showwindow(hWND, 1)

The only thing that happens after the 'window' is displayed is crash... and that may have been because of some incorrect handling, but, I am happy that I got it to work(for a little bit)! Just need to figure out the rest...

TekuConcept
  • 1,264
  • 1
  • 11
  • 21

3 Answers3

4

Instead of using Win32API (which I believe is built on top of the obscure and little used DL module), you might find better mileage using the new and improved FFI module.

Here's how:

  • (1) Get ffi:
    gem install ffi

  • (2) Then try this:

require 'ffi'

module Win32
   extend FFI::Library
   ffi_lib 'user32'
   attach_function :messageBox, 
       :MessageBoxA,[ :pointer, :string, :string, :long ], :int
end

rc = Win32.messageBox(nil, "Hello Ruby user!", "FFI is easy", 0x40)

puts rc

This seems easier than the solution you posted in your edit.

Note: The null pointer instead of Hwnd makes the message box have no owner window.


Here are some links that may help:
Community
  • 1
  • 1
Assad Ebrahim
  • 6,234
  • 8
  • 42
  • 68
  • You might want to consider using the parenthesis in your code @Assad just for the sake of copy and pasters like me. Example: see my answer above. It certainly works better for me after I copy your code. Anyway just fyi from a fan. – Douglas G. Allen Apr 10 '14 at 18:20
  • @DouglasG.Allen: Good suggestion. I would have thought you'd have just edited the answer to add the parentheses instead of copy pasting a new answer with just the two characters different. – Assad Ebrahim Apr 11 '14 at 19:16
  • Well it was for my reference as well as others. – Douglas G. Allen Apr 17 '14 at 04:13
0

I haven't tested this since I'm not on Windows but I think you're intended to use the constant DL::NULL. You can see it in action here (second-to-last line) and it looks similar to your use case. Hope that's helpful!

Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • I tried what you have suggested, over and over to confirm there was no error from me... the `require` lines worked successfully but when I run this line: `puts(DL::NULL)` it gives me this error: `NameError: uninitialized constant NULL`. `puts(DL)` returns `DL` just as intended. – TekuConcept Nov 11 '11 at 22:06
-1
require 'ffi'

module Win32
  extend FFI::Library
  ffi_lib 'user32'
  attach_function( 
                  :messageBox, 
                    :MessageBoxA,
                      [ :pointer, :string, :string, :long ], 
                      :int
                 )
end

rc = Win32.messageBox(nil, "Hello Ruby user!", "FFI is easy", 0x40)

puts rc
Douglas G. Allen
  • 2,203
  • 21
  • 20
  • I was able to successfully set up message boxes with both Win32API and ffi, but my true objective is an actual form - something I can draw to, supply buttons and text fields - something of the same functionality as QT in C++ and WinForms in C#. Thank you for your contribution! – TekuConcept Apr 11 '14 at 18:19
  • Perhaps try GTK+ as you could use it either in C or get the packages in Ruby gems. It can be tricky though. Lots of changes and somethings get deprecated and when you try to change it to the new suggestion you may get lost. They are just warnings mind you. They still work. http://www.gtk.org/ – Douglas G. Allen Apr 11 '14 at 18:29