Get Bitmap/DC of a tabbed MDI forms - winforms

I have a set of forms which are visualized as MDI tab children of a main form (through an Infragistics UltraTabbedMDIManager, but this API is not so important)
I use GetDC(), CreateCompatibleDC(), CreateCompatibleBitmap(), SelectObject(), BitBlt().. to blit the bitmap of the device contexts of these forms into some memory.
This works, but only for the active MDI child form, the one that is visible to the user.
If I do it for forms that are not active (any tabs that are not currently shown), I get a black screen in the memory area, or I even get a "copy" of the screen that's above it.
If I do it for forms that are no longer visible, I also get a black screen.
What should I do to get a bitmap of these hidden forms? Do I have to resort to caching or is there some other trickery I can use?
I cannot use Winforms DrawToBitmap() function, because the forms contain some low-level graphical things that cannot be retrieved with it.
How can I use the winapi to retrieve a bitmap of these "hidden" forms' DC?

I managed to do it using the PrintWindow API in user32.dll.
It solves the MDI tabs problem, however it didn't solve the problem for hidden forms.
I solved that problem by showign the forms briefly in some off-screen location.
It seems the "ultimate" way is to use the (undocumented) dwm.dll, but this is not so advisable because interfaces differ between versions of Windows.

Related

How does a GUI framework switch windows/window views/forms on Windows?

From what I understand, a GUI will have its windows, window classes, and use these for the main windows and all the buttons and tabs etc.
These would all have handles and be rendered either with the Windows GDI or another backend such as OpenGL. When a user interacts, say by clicking on a widget, there will be a callback function/event handler and it'll do its job. But what is happening when the user clicks on a button that switches the (I'm not sure what to call this so I'll call it a "form" - by this I mean the visible set of all menus and widgets and things - like on Google Chrome I have this tab open right now and I could move to another one that displays a different website and GUI) form.
How does the GUI framework change all the windows on the screen? I can understand it could change what's being rendered with the API of choice, like OpenGL, but how does it get rid of all the old windows and load the new ones? Does it disable all the child windows through their handles, and just leave them there on the screen, but unseen and not accepting input? Does it delete everything and create new windows? How does it actually perform this change (efficiently too)? I may be making a mountain out of a molehill here - if I'm overthinking this please let me know!
I once made a very bad game, using c Win32, the GDI and Direct2D, and when you pressed "play" it'd go to the game, but I just had to hide the buttons in a very glitchy fashion - I had no clue how to perform the "switch."
I have never ever used a "proper" GUI framework like Qt nor have I ever built one myself so apologies for any errata in the question, please correct me. I ask because I want to make my own GUI framework as a long term project (nothing special just something I can say that I've achieved) and I am at a loss as to how I can implement this from a low-level perspective, or rather how industry standards such as Qt will implement this at the lowest possible level.
Any answers would preferably not refer to managed code or any scripting languages, or external libraries - I want to know how to do this in c Win32 + any arbitrary graphics API. Thanks in advance.
This is accomplished by altering the z-order (the idea being that the windows form a stack from closest to the user to furthest away) of children at the appropriate level. The direct children of every window are in some z-order even if they are arranged such that they don't actually overlap.
For example, in the case of a tab control there will likely be a single child associated with each tab, that child representing the view for that tab. When a button is clicked the child for that tab is moved in the z-order so that is above all of its siblings (the forms for the other tabs). Those windows for the tab children will all be the same size (the empty area of the tab's client window) so bringing the child to the top of its parent's z-order will cover all other views.
In the case of the window's API you alter z-order placement via SetWindowPos, if you are going to roll your own (as WPF does) then you will need to re-implement this idea in some manner.

Moving (dragging) HwndHost using mouse

Here's what I am trying to accomplish - To create an MDI application in WPF, which can host child web applications. I am using WPF webbrowser control to render web applications. WPF inherently doesn't seem to support MDI applications, so after a bit of searching, I found this project, which uses UI controls to simulate windows and manages them inside a WPF canvas. This approach seems to work reasonably well until I start adding webbrowser control object as an MDI child.
When I add webbrowser control as an MDI child, it always appears on top of other WPF elements including other MDI child controls (as shown below). From what I understand, webbrowser control always appears on top of any other WPF object except for window (and popup). Assuming that's true, I think I need to use actual WPF window to avoid overlapping issue.
The only solution i can think of right now is to wrap WPF window inside an HwndHost object and then add that as an MDI child. However it appears that a child window cannot have title bar. That means that i need to have a window that has a dummy title bar area (just like actual window title bar) and actual content area (which will show webbrowser control) as shown below (Red border is HwndHost object).
This approach seems to solve the overlapping issue. The next thing i need to try is to let users click on the dummy title bar and drag the MDI window inside the canvas element.
Questions -
Is my understanding about WPF webbrowser control overlapping behavior right? If not, what am i missing?
Is the second approach a step in right direction for accomplishing what i want? If yes, how do i implement the drag behavior for HwndHost?
Is there any other alternate solution i can try?
Note:
Although many consider MDI not an elegant solution, I do not have a choice. (We tried alternate solutions like tabbed windows/dockable
windows, but were not well received)
I am quite new to interop programming, and do not understand the
concepts well. Please correct me if i am misunderstanding things.
Thanks!

Hooking into Forms redrawing

I'm looking for a way to overlay the graphical output of a third-party application with some lines, arcs etc. The applications accepts a handle of a window in which it will then display its output.
Using VC++ I put together a Windows Forms app in Visual Studio that draws (non-static) stuff in the onPaint-method of a form. Passing this form's handle to the other app, of course, overwrites my graphics stuff every time the other app redraws.
Can I somehow hook into this redrawing process to add my graphics after the other app redraws? Overlaying the form with a transparent panel onto which I draw could be an alternative. But real transparency for controls seem to be a problem of its own in Windows ...
You can't do this easily without getting notifications from the app. Which, if it doesn't provide them, would require setting a global hook with SetWindowsHookEx() so you can see the WM_ERASEBKGND and WM_PAINT messages. That's hard to get right, you cannot write such a hook in managed code. Since it requires injecting a DLL into the target process.
The only other option is that you put a transparent overlay on top of your form. Another form that has its TransparencyKey property set. The basic code you need to get that right is available in my answer in this thread. You just need to tweak it so it is permanent.

Wpf popups or modal windows as user entry screens?

I am building an application which has multiple user entry screens. I would like to know if there are advantages/disadvantages of using wpf popups rather than modal windows?
I am using mvvm-light.
I have noticed that popups are being used extensively in touch applications (eg iPad).
The issue is really one of Desktop vs. Web applications. Popups in Silverlight (or other touch apps) involve having only one real window to work with (the mobile surface, or the web browser). If you are writing a desktop app, then modal windows will probably match user expectations better as Popups cannot leave the parent window.
pop ups are nice but are very difficult to control. In our apps we are using adorners to be 'pop-up' editors - we have created a control that can hold any other control and display it in the adorner layer of the main window. This allows to do things such as having 1 control appear next to another yet still have the other control in use or we can grey out the background and force focus to the new control and not allow any other control to be used until the 'ok' button is pressed. If you Google for adorners in wpf you will find a lot of excellent articles.

How can I control the border thickness and color on Windows Forms?

I know that this can be controlled at the system level, but I want to override the system setting and have a certain appearance for only my application. I'm assuming there must be a Windows API function to control this because I've seen another windows app that does it.
(It is not necessary to go into the reasons why I should not do this)
If you want a custom appearance for your application, I would just make my form borderless and handle everything myself, either by drawing on the form itself in the Paint event, or else moving controls around (panels etc.) in the Resize event. You have to handle things like dragging, resizing, closing/minimizing etc., but none of this is especially difficult.
Here is my answer to a similar question, which shows the basics of doing it yourself (it's for windows mobile, but it will work in regular windows too).
These outer elements of an applications window are collectively referred to as the windows "chrome" and are indeed rendered by the operating system. Various flags are used at the windows API level to controls certain aspects of each window instance (e.g. the existing of a control box, border, min/max buttons, etc.), but the border width for resizable windows is determined by a system setting to ensure uniformity and is not configurable on a window by window basis.
You can, in many instances, gain control over some of the aspects of your window not exposed by .NET by interacting with the windows API and it is beneficial to read the windows API documentation to determine just what is possible at that lower level. I suggest reading the documentation for CreateWindowEx as a starting point.
http://msdn.microsoft.com/en-us/library/ms632680(VS.85).aspx
.NET allows you to change the FormBorderStyle property to select among no border, single pixel width border, and resizable (thick border). If you'd like to do something custom, you'll have to set the .NET border style to none, and then assume the responsibility for rendering the window chrome yourself. This entails rendering your own caption bar, min/max buttons, and window border. It's not a light undertaking, but many apps do it. It's a long way to go if all you really want is to control the border width.
This article goes into how one might approach this task in WPF, and may also be of use.
Window Chrome In WPF

Resources