wxWindowDC capture window-borders / title-bar

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

Hello,

i'm working on a small c++ video-wall application (currently win7 only). The basic idea simple:
The whole screen (wxScreenDX) or a specified window (wxWindowDC) shoud be captured in parts of e.g. 2 by 2 rectangels and transfered (via stretchBlit-method using transform-matrix) each in an own window. So far the theory...

In the beginning everything worked fine (except of the missing mousecursor on the captured image). But now something happened which i do not understand and the following problems have occured:
1. wxScreenDC: Somehow the captured image is frozen in the state of the first captured image after Programstart and - most strange - does not change even after restarting the program!!
2. wxWindowDC: The window-border and the title-bar of a single-window-source is not captured anymore and stays blank in the result.
3. wxWindowDC: The destination-windows border and the title-bar resist blitting.

All of these problems are new!!!
Since i make Backups of older states of my work, i found out that (1) and (2) do not occur in previous versions, while (3) has obviously also effect on old exe-files (without recompiling).

I tried a lot, but i have no idea anymore :?




-------------
Overview how the program works (ask for details if needed)...

Tree classes are used (all windows).

1) Mainwindow is a wxDialog containing controls for settings, the source-DC and a wxTimer-called loop.
2) Output-windows derived from wxFrame
3) Additional wxDialog for setting number of output-windows - not importent for the DC-problem

...where (2) and (3) are children of (1)


The Mainwindow (1) is initialized and shown on program-start, opening by defult two output-window-instances (2), where each creates a local wxWindowDC.
On toggeling the start-button the source-DC (wxWindowDC or wxScreenDC - selection by user) in (1) is initialized, and the wxTimer in (1) starts frequently calling the blitting-functions, which work like this:

Functions in mainwindow-class (1) called by Timer:
Timer-Event-function
- calls local "UpdateData" reading control-values defining borders, scaling etc.
- creates and sets transform-matrix for source-DC
- for each output-window-instance the Bilt-method is called in a loop

The Bilt-function is a method of the output-window-class (2) where:
- calls local "UpdateData" reading control-values defining per-ouput-window-settings
- creates and sets transform-matrix for destination-DC
- sets clipping-region for destination-DC
- calling stretchblit

That's all.


Any ideas what to do???


Regards,
Frank
Manolo
Can't get richer than this
Can't get richer than this
Posts: 827
Joined: Mon Apr 30, 2012 11:07 pm

Re: wxWindowDC capture window-borders / title-bar

Post by Manolo »

If you say your old work did the job, compare it with the new work.

I would pay attention to the fact that you must capture after the paint event is done. Painting is done asynchronously, and you can't know when the OS has finished painting. So, a bit of delay between the painting and the capture may be necessary.
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

Thanx for fast reply...

You're will be right in this point, but the painting-problem is not the first to be soluted. It may be some work to synchronize with windows-system repaint, but i don't want to invest the time as long as capturing doesn't work proper. So this is not so important... :wink:

The capturing also worked in before in older versions - and still does...
In the current builds wxScreenDC freezes and wxWindowDC doesn't capture the window-border, where space of the border is there, but no graphics inside - so only white.

The differences between older and newer version are:
  • - Some GUI and algorithm changed
    - Splitted some large functions in functional units
    - Moved the StrechBlit-call and its preparation from main-window-class(1) into output-class (which is maybe the reason for not overpainted borders in the output - PS. window is freezed - doesn't help)
    - Implemented function to select source at runtime
Concerning the two last points: I already put a test-blit into main-class and also re-disabled this function and reimplemented fixed source-DCs, but this do not change anything.

Also - as already said - the freezed full-screen capturing keeps its image when program is restarted - but only in the current version; in the previous version it still works proper - also after rebuilding.


Would be happy for any further idea...

Frank



PS. I'm not at home currently. Later i'll post source code and exe-files
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxWindowDC capture window-borders / title-bar

Post by doublemax »

Did anything else change between the different program versions, e.g. compiler and/or wxWidgets version?

I found this post which seems to describe a similar problem:
http://stackoverflow.com/questions/1149 ... n-aero-dwm

You didn't by any change disable the Aero theme programatically in your old application by calling DwmEnableComposition() ?
Use the source, Luke!
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

Nothing...

...except of - hmmm - there was an windows-update in between...
I'm not sure if tihs was exactly at the same time when the problem had occurd, because all tests changes which i had done in this time had concerned scaling at output, which still works. If i scale the output it is scaled and also my additionally implemented mouse-cursor moves.
Facit: I don't really know when the problen occurd first :|

I'm using DevC++ with wx 2.8.x

Now i'm back at home an can attetch files..... ... . ..


Attatched are two screenshots, concerning capturing of wxWindowDC with white window-border and title-bar. No wxScreenDC-problem snapsot (don't konw how to documet the frozen wxScreenDC).

Compete sources and exe-file you'll find here :
Current: http://www.art-ganseforth.de/wx/01.rar%20and - there is a memory-leak inside, but thie is not the problem. I'll delete ths comment if it is removed
Old: http://www.art-ganseforth.de/wx/01%20-% ... %20(3).rar

Unfortunatly there are no comments inside the sources. The importent prts are located in:
1) Main-Window: SceeenClonerFrm.cpp (in between a dialog)
2 )Output-Window: OutputFrm.cpp

Info:
- Numbers (1) and (2) are corrospnding to classes (1) and (2) in the original post
- At the end of the constructor of current SceeenClonerFrm.cpp (= main-window-class (1)) you'll find the line where source-DC is set:

Code: Select all

    srcDC               = new wxWindowDC(this);//new wxScreenDC();//
In file "OutputFrm.cpp", the wxFrame stored in pointer *DCwin, is the workaround to avoid output-window-borders. Normally the line:

Code: Select all

DC          = new wxWindowDC(DCwin);
should be this:

Code: Select all

DC          = new wxWindowDC(this);

(Would be nice if someone could test the project on another computer...)


Regards,
Frank
Attachments
Screenschot of current version with - by workaround - overpainted borders of the output-windows, but the displayed window inside has a white area instead of title an border
Screenschot of current version with - by workaround - overpainted borders of the output-windows, but the displayed window inside has a white area instead of title an border
Screenschot of old version (in current state with borders around output-windows), but the captured window within, is displayed including border, as it should be.
Screenschot of old version (in current state with borders around output-windows), but the captured window within, is displayed including border, as it should be.
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxWindowDC capture window-borders / title-bar

Post by doublemax »

That's a little too much code to look through thoroughly, but i see at least one problem in the "new" version. There are several places where you create a new wxScreenDC, but the old one is never destroyed. This can't be good.

Anway, i don't think it's written in any documentation and i'm not sure myself, but: My personal opinion is that you should never store and re-use any wxDC. Always create one if you need it and release (=destroy) it immediately.

And just out of curiosity: Does your employer force you to format the source like this? I've never seen anything like it and find it very hard to read.
Use the source, Luke!
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

This is - surely - not the problem, but...
you're right. I was not sure about deleting DCs. Previously i did but for testin i commented out the concerning lines (e.g. ScreenClonerFrm.cpp - line 336).
In between i found out myself, removed this single '//', and changed my last post in this point (adding a line concerning memory-leaks). Also, i removed one of the '//' in the code and replaced the uploaded file. But there is at least one more test-'//' to remove, which still leads to memory-leaks.

By the way: Do i have to (re-)create a DCs always, when i want to use it, or can i keep it in memory for several uses??? - in the old (working) version of the program i create them only once, but in wxScreenDC-documentation if found:
'This should normally be constructed as a temporary stack object; don't store a wxScreenDC object.'
..which confused me

Concerning 'too much code': I'll delete all the undeleted DCs and upload it again (maybe with some more comments) . may take until tomorrow...

In the zip-files, the exes are included. Did you try them? What is your result?
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxWindowDC capture window-borders / title-bar

Post by doublemax »

By the way: Do i have to (re-)create a DCs always, when i want to use it, or can i keep it in memory for several uses???
Create wxScreenDC and wxWindowDC on the stack and only when you need them. (The documentation mentions it for both classes). Actually i'd do that for any kind of wxDC.
In the zip-files, the exes are included. Did you try them? What is your result?
I don't use W7 and didn't have time to test it.
Use the source, Luke!
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

Thank you very much for your help so far.
Tomorrow i'll review my code and change all DCs to temporary. After this i'll continue this thread...

PS. doublemax: average 2.5 posts per day - for 8 years... Yeah... =D>
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

Hello,

i converted all DCs into temporary ones, but my problem is still the same.

Also i did some cleanup of my code and wrote lots of comments. The result i reuploaded it as http://www.art-ganseforth.de/wx/01.rar. All relevant functions are in "SceeenClonerFrm.cpp" (main-class) and "OutputFrm.cpp" (output-class)
Finally i made a some kind of flowchart to illustrate fuction-call-dependencies. I tried to attatch id to this post, which did not work So here is a download-link to my server: http://www.art-ganseforth.de/wx/14-09-0 ... Cloner.pdf.

Concerning the freezing ScreenDC-problem i found out, that every time when i run the program as administrator (win7 user-right-management) one new 'sample' of the screen is done. If there is running a second instance of the program, the new sample appears there also.

I'm totally confused about all of this, because i know it MUST work, while the old version still works fine...

Looking forward for answers...
Frank
User avatar
doublemax
Moderator
Moderator
Posts: 19115
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxWindowDC capture window-borders / title-bar

Post by doublemax »

I don't know where exactly the problem is. Maybe you should stripping down the code, uncommenting parts and comparing it to the old version.

There is one suspicious part that in saw in OutputFrm::Clear():

Code: Select all

DCwin->Show();          Freeze();              SetTransparent (1);         Raise ();
I'm surprised this doesn't result in an endless loop or at least 100% cpu load. You shouldn't make calls like this from inside a paint event handler. As this wasn't in the old version, try to comment this out first.

I don't know if this would solve the problem, but personally i'd take a very different approach to the task:
In the timer event handler, just grab the screendc, copy it in a bitmap and call Refresh() for all OutputFrms. In the paint event of OutputFrm, grab the above bitmap, make your transformation/scaling/etc and draw them onto the wxPaintDC.
Use the source, Luke!
art-ganseforth
Earned some good credits
Earned some good credits
Posts: 147
Joined: Mon Sep 01, 2014 10:14 am

Re: wxWindowDC capture window-borders / title-bar

Post by art-ganseforth »

YEAH!! I found the which progamline is responsible for the Problem!

It is this:

Code: Select all

    srcMatrix.Set(  wxMatrix2D      (scale.x, 0, 0, scale.y), 
                     wxPoint2DDouble (srcOffset.x - WxSpinPosX->GetValue(), srcOffset.y - WxSpinPosY->GetValue())
            );

    srcDC->SetTransformMatrix(srcMatrix);
Also i found out, the problem depends on scaling:
With "wxMatrix2D (1, 0, 0, 1)" the screen-capturing don't freeze and windows are captured including border but with "wxMatrix2D (0.9, 0, 0, 1)" it dosn't work.

This one:

Code: Select all

    srcMatrix.Scale (scale.x, scale.y);
    srcMatrix.Translate (srcOffset.x - WxSpinPosX->GetValue(), srcOffset.y - WxSpinPosY->GetValue());
also dosn't work; but without the scaling it is okay.
By the way: "CanUseTransformMatrix()" is true.

This is a big step foreward and open at least a way to some kind of "bypass". but i still have no idea what is wrog there. I can't really believe it, but is it possible that this is a bug in wxWidgets??





PS. This way:
doublemax wrote:In the timer event handler, just grab the screendc, copy it in a bitmap and call Refresh() for all OutputFrms. In the paint event of OutputFrm, grab the above bitmap, make your transformation/scaling/etc and draw them onto the wxPaintDC.
i will consider late, but dosn't this mor indirect way (via bitmap) need more CPU-usage?

PPS.
doublemax wrote:There is one suspicious part that in saw in OutputFrm::Clear():

Code: Select all

DCwin->Show();          Freeze();              SetTransparent (1);         Raise ();
I'm surprised this doesn't result in an endless loop or at least 100% cpu load. You shouldn't make calls like this from inside a paint event handler. As this wasn't in the old version, try to comment this out first.
The paint-event is commented out in the event-table - so the event-function it is currently not called.



Greetz,
Frank
Post Reply