none
OnPaint wrraper

    Question

  • Hi,

        I have successfully implement a global HOOK, and being able to get the following messages:

    CBTHook, ShellHook, WndProcHook.

    I want to be able to hook all the on paint messages to be able to traverse the painting commands and implement them.

    I want to create an application that get a process ID, and traverse all the messages to draw the application inside my application in parallel to the OS drawing. 

    Now, how I can do that?, the WndProcHook.WM_PAINT always include an empty wParam & lParam.

    Thanks,

    Markos

    Saturday, March 03, 2012 4:21 PM

Answers

  • Hi Markos,

    from my understanding, hooking up the WM_PAINT event will not tell you anything about the drawing that will take place. This message just tells the window that it should draw itself and does not contain any information on what to draw (Which belongs to the application logic and not to a windows message!).

    A description of WM_PAINT can be found at http://msdn.microsoft.com/en-us/library/dd145213(v=vs.85).aspx.

    I never tried something like that but maybe you can ask the window to draw itself into your window through the WM_PRINT message http://msdn.microsoft.com/en-us/library/dd145216(v=vs.85).aspx.

    With kind regards,

    Konrad

    Saturday, March 03, 2012 10:53 PM
  • The Graphics.CopyFromScreen is a quite nice solution but it will fail if the window is ot top most and something else is on top of the window. So maybe the CopyFromScreen method is not that usefull.

    http://www.fengyuan.com/article/wmprint.html explains the WM_PAINT a little more and gives an example, too (But it is C++ based).

    If you want to try the Solution of Dave, you might want to look at the following article on Codeproject: http://www.codeproject.com/Articles/25925/CWindow-A-wrapper-class-for-the-window-API-functio

    It shows you how you could modify existing windows so when you want to copy the window from the screen, you can simply make sure that it is TopMost and that no other window has that flag (Which will make this window TopMost now!). An afterwards you can revert your changes again.

    But this is not really optimal, too. You are working inside a multitasking environment. your application will tend to fail because other applications could do something, too. So they could react on the changes you did to them or revert them themself or a simple racing condition e.g. another windows opens up after your check of windows and before you copy the CopyFromScreen. So double-Check if that is a valid workaround or not.

    From my experience and what you wrote, the solution is to not hook up to get the window but to send the WM_PAINT message to the window. (And you can do a lot with simple messages to the windows and window parts. It can be a little more complex, because sometimes you need to allocate memory which the other process can write. In such a case you could check my blog article on how I managed to get a ListViewItem from another process: http://konradn.wordpress.com/2012/02/21/read-listviewitem-content-from-another-process/

    With kind regards,

    Konrad

    Edit: Forgot the link to the CWindow article on CodeProject!
    Sunday, March 04, 2012 7:57 AM
  • WM_PAINT does not use lParam or wParam, its only a notification and that's all. It is sent by the system to tell the window that a part of its client area is no longer valid, and that the program should revalidate that area by painting it. The same goes for WM_NCPAINT except for the non-client area it does include a handle to the clip region.

    I don't understand why you need a hook to do this. If a Window is covered by another window it is not painting its covered area, so I don't understand why you need a hook for this rather than a simple Graphics.CopyFromScreen with the bounds of the target Window, and draw that to your own bitmap.


    Currently developing FaultTrack. I occassionally blog about C# and .NET.
    Hoping to become a MVP by 2013. Email: danderson [at] dcomproductions [dot] com


    Sunday, March 04, 2012 12:57 AM
  • Hi Markos,

    it sounds interesting what you are trying to do. If you want to concentrate on single applications, the WM_PRINT could be a nice solution. If you want to provide more of a Remote Desktop, it could be better to use the CopyFromScreen. Both have different Advantages and Disadvantages.

    In general it could be usefull to investigate the existing solutions a little. What you are trying to do sounds a little like what Citrix is doing. It is a very interesting area and I can only recommend to look a little what other applications are doing (e.g. look at Citrix with applications like XenApp, XenDesktop, ...)

    Maybe it is worth looking at Codeproject and search there a little bit about Screen Capturing. There must be multiple articles covering that topic, too. E.g.:
    http://www.codeproject.com/Articles/12898/Screen-Capturing

    I am not sure, what other possibilities you will ind there, but it could be a try to even find more possibilities which we didn't mention so far.

    With kind regards,

    Konrad

    Sunday, March 04, 2012 12:09 PM
  • I see what you're trying to do now. IF you choose to experiment with Graphics.CopyFromScreen, see this image and the link below.

    http://www.dcomproductions.com/Stream/Image/ScreenCaptureProgram.png
    My topic from ages ago on StackOverflow here.

    You can write a very fast remote viewer using Graphics.CopyFromScreen that is efficient, but it is a lot of work and measuring constantly. However, I agree with Konrad that your solution is to hook and receive paint messages so you have the information ahead of time. However, I never experimented that route, so I don't know what is done exactly (I have a very good idea), but like Konrad stated things like Citrix GoToMeeting, RDP, and other similar applications would be a great help to you here. There are open source solutions that solve these problems around on the net as well.


    Currently developing FaultTrack. I occassionally blog about C# and .NET.
    Hoping to become a MVP by 2013. Email: danderson [at] dcomproductions [dot] com

    Sunday, March 04, 2012 7:54 PM

All replies

  • Hi Markos,

    from my understanding, hooking up the WM_PAINT event will not tell you anything about the drawing that will take place. This message just tells the window that it should draw itself and does not contain any information on what to draw (Which belongs to the application logic and not to a windows message!).

    A description of WM_PAINT can be found at http://msdn.microsoft.com/en-us/library/dd145213(v=vs.85).aspx.

    I never tried something like that but maybe you can ask the window to draw itself into your window through the WM_PRINT message http://msdn.microsoft.com/en-us/library/dd145216(v=vs.85).aspx.

    With kind regards,

    Konrad

    Saturday, March 03, 2012 10:53 PM
  • WM_PAINT does not use lParam or wParam, its only a notification and that's all. It is sent by the system to tell the window that a part of its client area is no longer valid, and that the program should revalidate that area by painting it. The same goes for WM_NCPAINT except for the non-client area it does include a handle to the clip region.

    I don't understand why you need a hook to do this. If a Window is covered by another window it is not painting its covered area, so I don't understand why you need a hook for this rather than a simple Graphics.CopyFromScreen with the bounds of the target Window, and draw that to your own bitmap.


    Currently developing FaultTrack. I occassionally blog about C# and .NET.
    Hoping to become a MVP by 2013. Email: danderson [at] dcomproductions [dot] com


    Sunday, March 04, 2012 12:57 AM
  • The Graphics.CopyFromScreen is a quite nice solution but it will fail if the window is ot top most and something else is on top of the window. So maybe the CopyFromScreen method is not that usefull.

    http://www.fengyuan.com/article/wmprint.html explains the WM_PAINT a little more and gives an example, too (But it is C++ based).

    If you want to try the Solution of Dave, you might want to look at the following article on Codeproject: http://www.codeproject.com/Articles/25925/CWindow-A-wrapper-class-for-the-window-API-functio

    It shows you how you could modify existing windows so when you want to copy the window from the screen, you can simply make sure that it is TopMost and that no other window has that flag (Which will make this window TopMost now!). An afterwards you can revert your changes again.

    But this is not really optimal, too. You are working inside a multitasking environment. your application will tend to fail because other applications could do something, too. So they could react on the changes you did to them or revert them themself or a simple racing condition e.g. another windows opens up after your check of windows and before you copy the CopyFromScreen. So double-Check if that is a valid workaround or not.

    From my experience and what you wrote, the solution is to not hook up to get the window but to send the WM_PAINT message to the window. (And you can do a lot with simple messages to the windows and window parts. It can be a little more complex, because sometimes you need to allocate memory which the other process can write. In such a case you could check my blog article on how I managed to get a ListViewItem from another process: http://konradn.wordpress.com/2012/02/21/read-listviewitem-content-from-another-process/

    With kind regards,

    Konrad

    Edit: Forgot the link to the CWindow article on CodeProject!
    Sunday, March 04, 2012 7:57 AM
  • Thanks Guys, I'll try the WM_PRINT option hopefully help me.

    The truth is that I want to simulate display (show the changes in an application and only display changes during the painting), and what I trying to do is to be able to get the changes in a specific application and send them to my application, but I'm trying to do that by catch the controls drawing and draw it in my application instead of polling the screen or the control, this can be helpful if I want to send the changes or draw commands to my application in other machine via lan.

    I think RDP protocol, traverse the draw commands to client, I want to do something like this using my own with few twist.

    This give better explanation, make any change to your answers?.

    One more thing, all hook think was because I want to know when the control that I'm listen to it have changes (pixel/drawing), yet I can't find which message can notify me about such changes, the redraw/paint does not. for example if I click on a button, I want to know about the display changes and move the changes on the "image" (button click state different than button in regular state) to my client.
    • Edited by Markos_King Sunday, March 04, 2012 10:02 AM
    Sunday, March 04, 2012 9:57 AM
  • Hi Markos,

    it sounds interesting what you are trying to do. If you want to concentrate on single applications, the WM_PRINT could be a nice solution. If you want to provide more of a Remote Desktop, it could be better to use the CopyFromScreen. Both have different Advantages and Disadvantages.

    In general it could be usefull to investigate the existing solutions a little. What you are trying to do sounds a little like what Citrix is doing. It is a very interesting area and I can only recommend to look a little what other applications are doing (e.g. look at Citrix with applications like XenApp, XenDesktop, ...)

    Maybe it is worth looking at Codeproject and search there a little bit about Screen Capturing. There must be multiple articles covering that topic, too. E.g.:
    http://www.codeproject.com/Articles/12898/Screen-Capturing

    I am not sure, what other possibilities you will ind there, but it could be a try to even find more possibilities which we didn't mention so far.

    With kind regards,

    Konrad

    Sunday, March 04, 2012 12:09 PM
  • I see what you're trying to do now. IF you choose to experiment with Graphics.CopyFromScreen, see this image and the link below.

    http://www.dcomproductions.com/Stream/Image/ScreenCaptureProgram.png
    My topic from ages ago on StackOverflow here.

    You can write a very fast remote viewer using Graphics.CopyFromScreen that is efficient, but it is a lot of work and measuring constantly. However, I agree with Konrad that your solution is to hook and receive paint messages so you have the information ahead of time. However, I never experimented that route, so I don't know what is done exactly (I have a very good idea), but like Konrad stated things like Citrix GoToMeeting, RDP, and other similar applications would be a great help to you here. There are open source solutions that solve these problems around on the net as well.


    Currently developing FaultTrack. I occassionally blog about C# and .NET.
    Hoping to become a MVP by 2013. Email: danderson [at] dcomproductions [dot] com

    Sunday, March 04, 2012 7:54 PM
  • Thanks guys, I'll lock at all the suggestion, and you are right it is very interesting project.


    • Edited by Markos_King Tuesday, November 05, 2013 9:15 PM
    Sunday, March 04, 2012 8:08 PM