I am updating an old application written in win32 in C and the requirement is to hide the mdi child windows based on some flags. I tried several methods but to no avail.
I tried ShowWindow with SW_HIDE but that doesn't work. The window just remains there blank (and generates no paint message). The same happens with SetWindowPos with SWP_HIDEWINDOW as one of the flags. SetWindowLong with ~WS_VISIBLE is the worst of the lot. It neither blanks the client area nor generates paint message, thus smearing it when other windows are moved over it.
Is it even possible to do it? If so, how?
PS: I did see a Delphi question here with the same requirement but I don't know Delphi and couldn't make out anything.
As was explained in earlier discussions, such as this one:
How to hide a MDI Child form in Delphi
MDI is simply not designed to allow child windows to be hidden, and Delphi's VCL has internal logic to prevent user code from trying to make that mistake. Trying to circumvent that logic causes unwanted side effects due to MDI's limitations.
In short, to "hide" an MDI child window, you have to destroy it, and then re-create it when you want to "show" it again. That is the only reliable option that MDI supports.
Related
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.
I'm now writing an Win32 SDK application. I need to create a modal child window for select from several options. My design is: Simply display them on the child window, if user press key 1, the 1st options is selected. other options are the same. After selection is made the child window close self automatically.
My problem is, is there a simple way to create such a child window? I have found two ways, both with some boring steps.
The first way is to create a dialog resource and use DialogBox function. It can easily create a modal child window. But since it is a modal dialog, system has filtered out all keyboard messages. I need to use some special tecs, like message hooking or something, to get these messages.
The second way is to register a class and directly call the CreateWindow(Ex) function. It can easily create a window with keyboard messages. But it seems to set it as a modal dialog is boring. I need to manually disable the parent window, set child window foreground, create a complete message loop for this window, and manually enable the parent window after it destroyed.
I have searched for a simple way to create a window with both of these 2 features. However found no clue apart from these 2 ways above. I'm not sure if this way exists. Can anyone tell me? My thanks for replies.
In my opinion working with the Win32 SDK is really complicated especially when you are creating a GUI (normally even creating a simple window can be challenge). Therefore would recommend the following to you:
Microsoft has a very neat API called MFC that comes with Visual Studio (I don't know if you can use MFC outside Visual Studio) and that has several C++ classes that wrap the Windows SDK methods, making things a lot easier for you. Furthermore Visual Studio lets you use a drag and drop interface to create your GUI (which I find really useful).
You can use a third party API to create your GUI elements like GTK or QT. Both are written in C/C++ and are very good APIs. Hopefully they will make your life easier when designing GUIs.
If using C/C++ is not a requirement for you, then I would strongly recommend that you use a higher level language like Java or C# to develop your application. I think that designing your GUI with them should prove a lot less troublesome that doing the same thing in C/C++.
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.
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.
I need to provide a Windows Forms control to a native application (Visual Studio).
So I create a control and provide its handle.
Then, when I check the native window using Spy++, I see that my control is wrapped in additional 'control' with window class = "Static" and title "This is a static!". I have several problems with it:
Resize events sent to my control by a hosting window have to be re-sent to the "Static" so it also gets resized (otherwise my control get partially hidden within the static's size).
The static does not have WS_EX_CONTROLPARENT, which causes KB149501 to appear (in short, whole application hangs on lost focus).
If I apply WS_EX_CONTROLPARENT, listbox within the static stops redrawing.
I think I have been doing something wrong, but I am not sure what. Google does not help, since static is a C# keyword as well so it occurs quite often in WinForms results.
I mostly solved the redrawing problem using DoubleBuffered=True, so probably this is it.
I still think I am doing something wrong, but at least it works now.