Custom shell window management

A

aflynt

Hello,

I've created a custom shell using .NET Windows Forms and integrated it
into my XPE image. It's working perfectly except for one caveat: I'm
having trouble keeping the shell 'behind' all of the other application
windows I'm spawning (Internet Explorer, Control Panel, etc...). I've
tried using the windows user32.dll API calls ShowWindow, and
SetForegroundWindow, and these work with some application windows, but
not others.

Does anyone have any experience with custom shell window management
that can give me some tips? Interestingly, I couldn't find much on the
net about actually writing custom shell code. Just a number of
articles about integrating your existing app into XPE as a custom
shell.

Thanks,
-=Aaron=-
 
J

John Coyne \(MS\)

Aaron,

Are you using VB or C#? I recently was playing with this in VB... I'd be
happy to share the Shell code I did... it's not pretty, but it does fully
work. :) if you contact me OL, I can send you the VS Project, as well as
the XPE Component for it.

as I recall, in VB, there's a behavior setting in the Properties pane for
the form.

HTH,
JC
 
K

KM

I am not sure I fully understood the issue.
What is the damaged behaviour when you spawn an IE window and your shell app window is hidden with ShowWindow(SW_HIDE) call?
 
A

aflynt

My custom shell is C# .NET Windows Forms 2.0 app, consisting of a
fullscreen window with icons on it that launch various other device
function and utility applications. When I launch applications that
have multiple non-modal windows, then click on the 'background' shell
app, all of the spawned windows are 'hidden' behind the shell.

My first approach for keeping the shell 'underneath' everything was to
loop through all of the running processes each time the shell received
focus and call ShowWindow, and SetForegroundWindow on their main
window handles. This only sort of worked. It was kind of ugly and slow
with all the windows flashing. Apps with multiple windows open would
also wind up with all windows but one still underneath the shell.

Right now what I'm doing is creating modal windows as part of the
shell application to perform as many of the functions as possible. For
example, I've created an Internet Browser form with an embedded MSHTML
control for functions requiring web browser access. For utilities and
functions that would be too time consuming to recreate in my shell
app, I've found that calling SetWindowPos on the Shell window with the
HWND_BOTTOM flag each time it receives focus works fairly well. It's
not as slow and ugly as the first method, and all of the non-minimized
windows will stay on top of the shell. The only potential point of UI
confusion for the user now is window minimization. Windows appear to
minimize to a small rectangular title bar in the lower left hand
corner (which is fine). Unfortunately, the minimized window winds up
below the shell until the shell is given focus and the SetWindowPos
function is called again.

I was just wondering how other people approach problems like these
that seem common to custom shell creation. Is running the app
fullscreen an uncommon way of creating a shell? Are there any good
books or web resources for designing custom shells?

Thanks again,
-=Aaron=-
 
K

KM

Hi Aaron,

I'd recommend you to create your shell app with CreateWindowEx API (or .Net equivalent) with the WS_EX_NOACTIVATE ex-style set. Then
the window will not become the foreground window when the user clicks it. The system will not bring this window to the foreground
when the user minimizes or closes a foreground window.

Also, you probably want to add WS_EX_TOOLWINDOW ex-style there as well to remove the window from Alt-Tab list.

Also, I'd recommend you to use SetWindowPos ( HWND_BOTTOM ) in the window proc every time you get WM_ACTIVATE notification (wParam=
WA_ACTIVE or WA_CLICKACTIVE). In general it is not required to have with the WS_EX_NOACTIVATE ex-style used but doesn't hurt to
have.

--
=========
Regards,
KM


My custom shell is C# .NET Windows Forms 2.0 app, consisting of a
fullscreen window with icons on it that launch various other device
function and utility applications. When I launch applications that
have multiple non-modal windows, then click on the 'background' shell
app, all of the spawned windows are 'hidden' behind the shell.

My first approach for keeping the shell 'underneath' everything was to
loop through all of the running processes each time the shell received
focus and call ShowWindow, and SetForegroundWindow on their main
window handles. This only sort of worked. It was kind of ugly and slow
with all the windows flashing. Apps with multiple windows open would
also wind up with all windows but one still underneath the shell.

Right now what I'm doing is creating modal windows as part of the
shell application to perform as many of the functions as possible. For
example, I've created an Internet Browser form with an embedded MSHTML
control for functions requiring web browser access. For utilities and
functions that would be too time consuming to recreate in my shell
app, I've found that calling SetWindowPos on the Shell window with the
HWND_BOTTOM flag each time it receives focus works fairly well. It's
not as slow and ugly as the first method, and all of the non-minimized
windows will stay on top of the shell. The only potential point of UI
confusion for the user now is window minimization. Windows appear to
minimize to a small rectangular title bar in the lower left hand
corner (which is fine). Unfortunately, the minimized window winds up
below the shell until the shell is given focus and the SetWindowPos
function is called again.

I was just wondering how other people approach problems like these
that seem common to custom shell creation. Is running the app
fullscreen an uncommon way of creating a shell? Are there any good
books or web resources for designing custom shells?

Thanks again,
-=Aaron=-
 
A

aflynt

Okay. I've finally had a chance to play around with this again. I
figured out how to set Ex window creation flags in .NET by subclassing
System.Windows.Forms.Form and overriding CreateParams. Setting the
WS_EX_NOACTIVATE and WS_EX_TOOLWINDOW works very nicely for keeping
maximized windows on top. Unfortuantely, when newly spawned windows
are minimized, the little window icon is still sometimes layered
behind the shell window. I looked into creating a global window hook
to trap all of the minimize messages, but apparently that isn't
possible in .NET at all (global hooks only work for mouse and keyboard
messages).

I suppose I could go back and remove the minimize box from all the
windows in my utility apps, and create minimize boxless replacements
for everything else. Any other ideas?
 
K

KM

Aaron,

Quite frankly, I always do such low level Win32 work in unmanaged C++ where there is almost no limitations on what can be done for
all the windows in the system. For instance, it is relatively easy to create a global hook (on window creation event, for example)
there and change all window attributes to remove system buttons and system menu items (minimize button, etc.). I've done that
multiple times and was able to control most of the parameters of all the windows in the system, but again - I did that in unmanaged
code.

In .Net there are limitations obviously with what you can implement within the managed code. You can always p-invoke unmanaged
though. Just call out SetWindowsHookEx (P-Invoke it) and set up CBT hook.

Another quick and dirty workaround would be to handle WM_ACTIVATE event for your shell app window and, every time the window gets
activated, enumerate all other top-level windows and bring them to the front if they are minimized (iconic) or so. Obviously, you
can't use WS_EX_NOACTIVATE ex-style for the shell window then.

--
=========
Regards,
KM


Okay. I've finally had a chance to play around with this again. I
figured out how to set Ex window creation flags in .NET by subclassing
System.Windows.Forms.Form and overriding CreateParams. Setting the
WS_EX_NOACTIVATE and WS_EX_TOOLWINDOW works very nicely for keeping
maximized windows on top. Unfortuantely, when newly spawned windows
are minimized, the little window icon is still sometimes layered
behind the shell window. I looked into creating a global window hook
to trap all of the minimize messages, but apparently that isn't
possible in .NET at all (global hooks only work for mouse and keyboard
messages).

I suppose I could go back and remove the minimize box from all the
windows in my utility apps, and create minimize boxless replacements
for everything else. Any other ideas?
 
A

aflynt

Unfortunately, P-Invoking any global hook other than mouse or keyboard
doesn't work due to the way .NET is architected. I tried enumerating
and focusing windows on activate before, and the end result wasn't
pretty :) What actually worked better was sending the shell window to
the bottom on activate (SetWindowPos ( HWND_BOTTOM )), but it still
slowed down the UI quite a bit.

I'm contemplating extracting out all the non trivial stuff into
separate apps, doing the core shell in C++ Win32 API and
ShellExec(ing) out for everything. I did a simple test C++ Win32 shell
a few days ago, and performance and memory usage was much better than
the .NET version (1/10th memory usage).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top