tags:

views:

17

answers:

1

I need to write a screencast, and need to detect when window content has changed, even only text was selected. This window is third party control.

+1  A: 

Ther're several methods.

(1) Screen polling.

You can poll the screen (that is, create a DIB, each time period to BitBlt from screen to it), and then send it as-is

Pros:

  • Very simple to implement

Cons:

  • High CPU load. Polling the entire screen number of times per second is very heavy (a lot of data should be transferred). Hence it'll be heavy and slow.
  • High network bandwidth

(2) Same as above, except now you do some analyzing of the polled screen to see the difference. Then you may send only the differences (and obviously don't send anything if no changes), plus you may optionally compress the differences stream.

Pros:

  • Still not too complex to implement
  • Significantly lower network bandwidth

Cons:

  • Even higher CPU usage.

(3) Same as above, except that you don't poll the screen constantly. Instead you do some hooking for your control (like spying for Windows messages that the control receives). Then you try learn when your control is supposed to redraw itself, and do the screen polling only in those scenarios.

Pros:

  • Significantly lower CPU usage
  • Still acceptable network bandwidth

Cons:

  • Implementation becomes complicated. Things like injecting hooks and etc.
  • Since this is based on some heuristic - you're not guaranteed (generally speaking) to cover all possible scenarios. In some circumstances you may miss the changes.

(4) Hook at lower level: intercept calls to the drawing functions. Since there's enormous number of such functions in the user mode - the only realistic possibility of doing this is in the kernel mode.

You may write a virtual video driver (either "mirror" video driver, or hook the existing one) to receive all the drawing in the system. Then whenever you receive a drawing request on the specific area - you'll know it's changed.

Pros:

  • Lower CPU usage.
  • 100% guarantee to intercept all drawings, without heuristics
  • Somewhat cleaner - no need to inject hooks into apps/controls

Cons:

  • It's a driver development! Unless you're experienced in it - it's a real nightmare.
  • More complex installation. Need administrator rights, most probably need restart.
  • Still considerable CPU load and bandwidth

(5) Going on with driver development. As long as you know now which drawing functions are called - you may switch the strategy now. Instead of "remembering" dirty areas and polling the screen there - you may just "remember" the drawing function invoked with all the parameters, and then "repeat" it at the host side.

By such you don't have to poll the screen at all. You work in a "vectored" method (as opposed to "raster").

This however is much more complex to implement. Some drawing functions take as parameters another bitmaps, which in turn are drawn using another drawing functions and etc. You'll have to spy for bitmaps as well as screen.

Pros:

  • Zero CPU load
  • Best possible network traffic
  • Guaranteed to work always

Cons:

  • It's a driver development at its best! Months of development are guaranteed
  • Requires state-of-the-art programming, deep understanding of 2D drawing
  • Need to write the code at host which will "draw" all the "Recorded" commands.
valdo
Thanks for your answer. For my task 3rd method will approach (spying for windows messages). I know about wm_paint, but it's not enough. Can you give more comment on this way?
Schnider
`WM_PAINT` is not enough, because the control may draw itself in-place, (it will just `GetDC` and draw itself). You should also look at particular cases with `WM_COMMAND`. Sometimes mouse messages also should be considered.
valdo
It's just I've tried all the described scenarios. And, I must say, in the "general case" (unknown control or app) - it will not reliably work. A particular control however may be done in such a way.
valdo