Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
511 views
in Technique[技术] by (71.8m points)

winapi - How to detect when window content has changed

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...