How to get a Window handle from another app?

Hello,

I would like to get a window handle from another app outside of wxRuby
and convert it into a wxRuby Window handle so that I can use it as the
parent Window for several wxRuby child windows. Basically I want to use
the FRAME_FLOAT_ON_PARENT window style so that my wxRuby windows become
associated with the outside app kind of like toolbars, e.g., they don’t
show up in the taskbar and are always floating on top of my target app.

Going through the archives I found a related question here, but I think
it’s the opposite of what I want to do:

http://rubyforge.org/pipermail/wxruby-users/2007-December/003485.html

I already have wxRuby and my target app talking to each other pretty
well, it would just make for a cleaner interface to make the target app
into the parent window somehow.

Oh, and did I mention?, I’m looking for a cross-platform solution for
Windows and OSX! Or I’ll just settle for Windows-only if I have to.

Any ideas?

Thanks,

P

Hi

Ellis, Peter wrote:

I would like to get a window handle from another app outside of wxRuby
and convert it into a wxRuby Window handle so that I can use it as the
parent Window for several wxRuby child windows. Basically I want to
use the FRAME_FLOAT_ON_PARENT window style so that my wxRuby windows
become associated with the outside app kind of like toolbars, e.g.,
they don’t show up in the taskbar and are always floating on top of my
target app.

[plain text is preferred on this list, please]

This reference from C++ wxWidgets and a few others seem to suggest a
HWND window identifier can be linked to a Wx::Window using the
AssociateHandle method call:
http://www.wxwidgets.org/wiki/index.php/WxWidgets_For_MFC_Programmers#Associating_HWNDs_with_wxWindow_instances

However, although the AssociateHandle call is listed in the headers,
it’s not listed in the wxWidgets documentation. So at present it’s not
available in wxRuby. I will see if it’s possible to add this call for
the next release.

alex

Thanks, Alex. That sounds very promising. I know I can get an HWND in
Ruby using the Win32API library in Windows. Just curious how might that
work in OS X? I’ve been mainly developing my app on Windows, but it
will also need to work on OS X eventually.

P

Ellis, Peter wrote:

Thanks, Alex. That sounds very promising. I know I can get an HWND in
Ruby using the Win32API library in Windows. Just curious how might that
work in OS X? I’ve been mainly developing my app on Windows, but it
will also need to work on OS X eventually.
I had a look at the wxWidgets headers, and it seems that AssociateHandle
and SetHandle aren’t implemented on OS X, so it won’t work the same way.
GetHandle is, and I’m pretty sure you can already get a meaningful
system window id on OS X with get_hwnd. Whether you can do anything
useful with this + RubyCocoa I don’t know.

alex

Does anyone know of a chart making extension written with wxRuby? I
know there are a few Ruby gems out there to make charts (as SVG or an
image), but they seem to have a lot of overhead associated with them.
The ones I’ve found that seem most interesting (Gruff, Scruffy, gnuplot)
require a big bulky graphics/image processing library to be installed.
Seems like wxRuby has all the pieces one would need to make a nice chart
API or custom chart widget, although probably without the SVG, which is
fine for my purposes.

Thanks.

Thanks, Alex.

I was hoping that we wouldn’t have to create our own, but we might do it
if that turns out to be the best solution. I’ll keep the list posted.

I did find this project, but it looks dead.
http://rubyforge.org/projects/wxryplot/
http://files.rubyforge.vm.bytemark.co.uk/wxryplot/WxRyPlot.doc

P

Ellis, Peter wrote:

Does anyone know of a chart making extension written with wxRuby? I
know there are a few Ruby gems out there to make charts (as SVG or an
image), but they seem to have a lot of overhead associated with them.
The ones I’ve found that seem most interesting (Gruff, Scruffy, gnuplot)
require a big bulky graphics/image processing library to be installed.
Seems like wxRuby has all the pieces one would need to make a nice chart
API or custom chart widget,
Yes, all the pieces should be there. There are several charting
libraries written in C++ for wxWidgets which might offer a good starting
point [1]

Basically, you use a DC (DeviceContext) to draw lines, polygons,
ellipses, text etc. DC can draw images from files and do textured fills.
Wx::Grid would be an excellent component for editing and viewing the
source data points.

The target canvas can be either the screen (using Window#paint to create
a PaintDC), or a bitmap (using Bitmap#draw to create a MemoryDC). The
same actual drawing code is used regardless of the target. Once the
drawing’s been done on a bitmap, call Bitmap.save_file to save the image
to a variety of formats, including BMP, PNG, TIF or JPG.

For higher-quality output there’s also GraphicsContext, which can be
created by calling GraphicsDC.create(dc) from any other DC. This will
give anti-aliased edges and also offers gradient fills but is otherwise
very similar.

although probably without the SVG, which is fine for my purposes.

There’s an SVG-writer as an optional contrib-module in the main
wxWidgets tree, which allows DC drawing code to be output as SVG. This
isn’t currently porrted to wxRuby, but if there’s interest we could have
a look at adding it.

In my day job I do a lot of charting in Excel and SPSS so I’d be
interested to hear how it goes if you decide to pursue this.

cheers
alex

[1]
http://wxcode.sourceforge.net/complist.php?compperpage=1000&viewmode=full&browseby=category&section=graphics&page=1

Ellis, Peter wrote:

Thanks, Alex.

I was hoping that we wouldn’t have to create our own, but we might do it
if that turns out to be the best solution. I’ll keep the list posted.

Following your earlier message I had a closer look at Scruffy and Gruff.
Scruffy has the drawing code very nicely separated from the logic that
organises the chart elements. So in about 20 mins I was able to replace
enough of the svg-based drawing code with dc-based code to get it to
draw the chart background, title, frame, axis and labels in a Wx::Window
(see below for the app code)

It’s a fairly mechanical job of replacing calls to svg.text with
dc.draw_text, svg.line with dc.draw_line etc in scruffy/components and
scruffy/layers. I’m sure the individual chart types would need a little
more work, but each is still only a couple of calls to the same basic
methods. I would recommend looking into it.

hth
alex

__
require ‘scruffy’
require ‘wx’

class Chart < Wx::Window
attr_reader :graph
def initialize(*args)
super
evt_paint :on_paint
@graph = Scruffy::Graph.new(:title => “Monthly Profits”)
graph.add(:line, ‘John’, [100, -20, 30, 60])
graph.add(:line, ‘Sara’, [120, 50, -80, 20])
end

def on_paint
paint do | dc |
graph.render(dc, :width => size.width, :height => size.height)
end
end
end

Wx::App.run do
frame = Wx::Frame.new(nil, :title => ‘chart demo’)
chart = Chart.new(frame)
frame.show
end

Hello,

sounds interesting. A chart extension would be very useful for me.
Any news yet?

Sven

Am Donnerstag, 2008-Januar-31 20:47:04 schrieb Ellis, Peter:

That’s fantastic! I’ll definitely took a closer look at this.

P

Am Donnerstag, 2008-Januar-31 20:41:58 schrieb Alex F.:

I had a look at it, but it still looks too complex for me.
Can anybody provide some concrete code pieces?

Any help appreciated.

Sven

Andreas W. wrote:

I would like to render a graph directly to the screen - is this possibly
using scruffy / wxruby?
Or, the simplest route would just to be to install a ruby extension that
renders SVG to PNG or some other raster format that wxRuby can read, and
then display that.

I think ImageMagick can rasterize SVG in this way.

alex

Alex F. wrote:

require ‘scruffy’
require ‘wx’

class Chart < Wx::Window
attr_reader :graph
def initialize(*args)
super
evt_paint :on_paint
@graph = Scruffy::Graph.new(:title => “Monthly Profits”)
graph.add(:line, ‘John’, [100, -20, 30, 60])
graph.add(:line, ‘Sara’, [120, 50, -80, 20])
end

def on_paint
paint do | dc |
graph.render(dc, :width => size.width, :height => size.height)
end
end
end

Wx::App.run do
frame = Wx::Frame.new(nil, :title => ‘chart demo’)
chart = Chart.new(frame)
frame.show
end

This won’t run. I get ‘in `render’: wrong number of arguments (2 for 1)
(ArgumentError)’ when I copy your example verbatim.

Removing the extra argument in render and rerunning gives me:

C:/ruby/lib/ruby/gems/1.8/gems/scruffy-0.2.2/lib/scruffy/graph.rb:131:in
`render’: undefined method ‘[]’ for #Wx::PaintDC:0x591d318
(NoMethodError)

I would like to render a graph directly to the screen - is this possibly
using scruffy / wxruby?

Regards
Andreas

Alex F. wrote:

I think you’ve misunderstood the purpose of the example. It was just to
show a set up where a scruffy graph would render using a wxRuby DC
(device context) rather than to an SVG object.

What remains for someone with motivation to do is to convert or
translate the calls that scruffy makes to an svg object inside the
library (eg svg.line, svg.circle) into the equivalent DC calls
(dc.draw_line, dc.draw_circle). The relevant parts of scruffy to look at
are in the components and layers directory.

You’re right I did misunderstand. I might pursue your first suggestion
to create the svg and the load it as an image, though it is suboptimal.

I understand you can divert the output procedure to the screen but since
it is not a part of the “standard package” - and I thus need to write it
myself - I don’t think it is a good route to take, considering time and
reliability.

Thanks!

Andreas

Andreas W. wrote:

Alex F. wrote:

require ‘scruffy’
require ‘wx’

class Chart < Wx::Window

This won’t run. I get ‘in `render’: wrong number of arguments (2 for 1)
(ArgumentError)’ when I copy your example verbatim.

I think you’ve misunderstood the purpose of the example. It was just to
show a set up where a scruffy graph would render using a wxRuby DC
(device context) rather than to an SVG object.

What remains for someone with motivation to do is to convert or
translate the calls that scruffy makes to an svg object inside the
library (eg svg.line, svg.circle) into the equivalent DC calls
(dc.draw_line, dc.draw_circle). The relevant parts of scruffy to look at
are in the components and layers directory.

Probably it would be easiest to create a bridge class that translates
svg calls as dc calls. Then you could use the the Scruffy library
unmodified.

I did enough to persuade myself that this was likely a viable approach,
but have no particular interest in pursuing at the moment.

I would like to render a graph directly to the screen - is this possibly
using scruffy / wxruby?
No, not directly without you or someone else doing some work.

The other approach would be to wrap a C++ wxWidgets component that
renders SVG (such as wxArt2D) in Ruby. This is probably harder.

alex

alex

I just wanted to report back to the list on one chart-making technique
that has been working out well for me so far. I am using a popular open
source scientific and mathematical plotting package called Gnuplot.

http://www.gnuplot.info/

To use Gnuplot I started with a Ruby wrapper called rgplot (found on
RubyForge).

http://rubyforge.org/projects/rgplot

After playing with rgplot a while, I came to the conclusion that the
interface wasn’t really suited for my needs, so I studied the code,
learned a few key things, and ultimately came away with the one or two
lines of code that setup the pipe between Ruby and Gnuplot. Then I
wrote my own proof-of-concept wrapper to plot a couple of charts:
clustered bar charts, stacked bar charts, line graphs, etc.

Unfortunately, my wrapper is not really good enough for public
consumption, but I can explain how it works and you might be able to use
the same idea for your own applications. Basically, Gnuplot is run as a
subprocess from Ruby. You pass whatever commands and data you want to
Gnuplot through a stream to that subprocess. When it’s done plotting,
Gnuplot writes an image file to disk (JPG or other format). Finally you
create a Wx::Image from the image file and draw it as Wx::Bitmap on a
dc.

You can get pretty nice looking charts out of Gnuplot but you might have
to work at it. The Gnuplot syntax can be a pain, but it does come with
a lot of example files that help a lot. It also has an interactive GUI
that is handy for testing command syntax. One thing that Gnuplot cannot
do is pie charts. However, if you really need pie charts, they would be
easy enough to implement yourself by drawing directly with wx.

To implement your own wrapper for Gnuplot, I definitely recommend
studying rgplot (or use it “as is”, if it works for you). One thing to
look out for is that Gnuplot will be running asynchronously from
whatever else you are doing in Ruby or wx. So I use the on_timer event
to watch for the image file to be completed. After a lot of
experimentation, I found that (File.exists?(path) and File.size(path) >
0) is the best test to see if the image file is actually ready to be
loaded into wx. Also, if you need to create multiple charts at the same
time, you will need to write a manager that sequentially feeds jobs to
Gnuplot and then collects the resulting images. I was able to do that
without too much trouble, again using the on_timer event.

Maybe someday I’ll be able to put together a wrapper that I would be
willing to share. At the moment I’m not working on this actively, but I
hope to get back to it in a few months.

Best of luck,
P