I have an application that, due to OpenGL airspace issues, has to host several controls in separate, exclusive windows. This is working quite well, but I am setting all of the windows to TopMost = true, which means that they do stay showing even when they lose focus, but they also overlay other applications. Also, it kind of binds me to using only one window at a time for this. Activate() doesn't work either.
I found that setting the windows' owners to the main app window allowed them to always float on top.
Inside the control that mediates the content and measurement of the child window:
InnerWindow.Owner = Window.GetWindow(this);
this being the windowHostControl hosting this window.
I use to combine Activate() and Focus() methods to show a hidden Window. Can you try using Focus() and let us know if this is working ?
Related
I have inherited a large MFC application which contains a CComboBox subclass that overrides OnPaint. Currently it does all its drawing by hand (with lines and rectangles), and renders a combo box that looks decidedly Windows 98-style. However, it otherwise works great and provides a lot of useful custom functionality that we rely on, and rewriting the entire control is probably not an option.
I would like to modernize it so that the OnPaint draws in Aero style where available (falling back to the old code when modern theming is unavailable). I've done this with some other custom controls we have, like buttons, and it works great for our purposes. I know there are some tiny behaviors that it won't get right, like gentle highlights on mouse-hover, but that's not a big deal for this app.
I have access to the CVisualStylesXP ckass, so I've already got the infrastructure to make calls like OpenThemeData, GetThemeColor or DrawThemeBackground pretty easily (via LoadLibrary so we don't force Vista as a min-system). Unfortunately, I don't know the proper sequence of calls to get a nice looking combo box with the theme-appropriate border and drop-down button.
Anyone know what to do here?
Honestly, I don't know why they originally tried to override OnPaint. Is there a good reason? I'm thinking that at least 99% of the time you are just going to want to override the drawing of the items in the ComboBox. For that, you can override DrawItem, MeasureItem, and CompareItem in a derived combo box to get the functionality you want. In that case, the OS will draw the non-user content specific to each OS correctly.
I think you best shot without diving in the depth of xp theming and various system metrics is take a look at this project: http://www.codeproject.com/Articles/2584/AdvComboBox-Version-2-1
Check the OnPaint of the CAdvComboBox class - there is a full implementation of the control repainting including xp theme related issues.
Not sure if it's the same situation - but when I faced this problem (in my case with subclassed CButtons), solving it only required changing the control declaration to a pointer and creating the control dynamically.
Let's assume that your subclassed control is called CComboBoxExt.
Where you had
CComboBoxExt m_cComboBoxExt;
You'll now have
CComboBoxExt* m_pcComboBoxExt;
And on the OnInitDialog of the window where the control is placed, you create it using
m_pcComboBoxExt = new CComboBoxExt();
m_pcComboBoxExt->Create(...)
Since this is now a pointer, don't forget to call DestroyWindow() and delete the pointer on termination.
This solved my particular problem - if your control is declared in the same way, consider giving it a try.
Due to an unsolved issue in my current project [ Weird scrollbar UI in hosted WPF composite control ], I've had to defer to workarounds. One such idea I came up with was to keep the ScrollViewer in question in sync with a Windows Forms ScrollBar (horizontal and vertical). How would I go about doing that?
In essence, I want the WinForms scrollbar(s) to work like the ScrollViewers (in terms of dragging and events suchlike).
I think there's no any other way than send/listen to the lo-level API Windows messaging. You should have a decent knowledge of the Win APIs, and how to manage them. I'd add also that the scrollers are mid-complexity task to manage, but maybe it's me...
Here is the vertical scroll message reference.
I managed to implement it without having to much around with the WinAPI. Here's how I did it:
Registered a ScrollOffsetChanged event handler with the scrollviewer (the composite control that implemented the IScrollInfo interface exposed the event).
Registered a ValueChanged event handler with the windows forms scrollbar.
A couple of signal flags to prevent cyclic calls to the event handler.
The first handler called an UpdateExternalScrollBars() function that calculated the Maximium Scrollbar property using the following expression: ScrollViewer->ExtentHeight/Width - ScrollViewer->ViewportHeight/Width. The Value property was directly set to ScrollViewer->Vertical/HorizontalOffset.
The second fetched the Value property from the windows forms scrollbar and passed it to ScrolViewer->ScrollToVertial/HorizontalOffset(). The signal flags were appropriately set beforehand.
How can I restart WPF application from code? in Windows Forms there is Application.Restart, where for whatever reason Microsoft decided not to add this method in WPF.
I hate the discompatability between WPF and WindowsForms! like:
window.Visibility = System.Windows.Visibility.Hidden;
What's wrong with that?
window. Visible = false;
Visibility
For controls and panels, there is a huge difference between Visibility.Collapsed and Visiblity.Hidden. Hidden reserves the space of the invisible element, Collapse frees the used space. This can make a big difference in an UI.
Using the same enumeration for the visibility of the window-class is IMO first of all a question of holding a constancy in the class-library, but may be it makes also some other finer differences.
Restart
If there is a possibility to directly restart the app, I don't know. What you can try is to use App.Current.Shutdown() to close the app and start a new instance through System.Diagnostics.Process.Start() where the path to the app can be taken from System.Reflection.Assembly.GetEntryAssembly(). `.
We have an MFC ActiveX control created in Visual Studio 2008 with CLR support which creates a WPF grid and shows a WPF window within that grid.
This ActiveX is hosted within Internet Explorer and it shows up and works nicely except that the tab key, backspace, function keys etc. does not work since they are handeled by IE instead of the WPF window. Regular characters works nicely. This is a known feature and previously when we used to have MFC based dialogs within this ActiveX we used this: http://support.microsoft.com/kb/187988. By just using this code directly the
AfxGetApp()->PreTranslateMessage((LPMSG)lParam)
statement will return FALSE, so I'm not able to get the key stroke to be handled by the WPF window. I beleive I need to ask the WPF application this instead of the CWinApp, but I'm not sure how and if this can be done. Does anyone have enough understanding of what's going on here to get this to work?
Using XBAP instead of ActiveX is not an option as this is run in an intranet application which needs more access than the sandbox can give us.
I hope this is enough information.
With best regards
Svein Dybvik
We have hosted a WPF user control inside an MFC modeless dialog. In order to get some keyboard stuff working correctly, we had to modify the dialogs PreTranslateMessage() function.
Basically, what we did was to check to see if the message was for the WPF window. If it was, we immediately call TranslateMessage/DispatchMessage and then return TRUE from PreTranslateMessage.
Our WPF control fills the entire dialog, so you'd have to have your own conditional check where we have the IsChild test.
BOOL CHostDlg::PreTranslateMessage(MSG* pMsg)
{
// normal PreTranslateMessage() causes the edit fields not to work
if (::IsChild(GetSafeHwnd(), pMsg->hwnd))
{
TranslateMessage(pMsg);
DispatchMessage(pMsg);
return TRUE;
}
return baseclass::PreTranslateMessage(pMsg);
}
Some edit:
BOOL CHostDlg::PreTranslateMessage(MSG* pMsg)
{
// normal PreTranslateMessage() causes the edit fields not to work
if (::IsChild(GetSafeHwnd(), pMsg->hwnd))
{
TranslateMessage(pMsg);
DispatchMessage(pMsg);
pMsg->hwnd = GetSafeHwnd(); // redirect to parent
}
return baseclass::PreTranslateMessage(pMsg);
}
I want to setup my WinForm to look like the Delphi7 IDE. Basically that means the window has no background (the desktop shows through), and child windows float around.
Here's a sample image:
I can handle the floating windows, but how would I go for the main window (the menu bar and the toolbar)? What are the WinForm properties required to get this layout? I can't seem to be able to get rid of the window's client area.
Thank you
Why can't you get rid of the client area? Just resize the main form so that it's as thin as you can make it.
You may be implementing the floating windows as UserControls in the main form's Controls collection. If so, there are two ways you can deal with this:
Implement the floating windows as actual windows. Show them using "frmToolWindows.Show(this);" (this will keep them always on top of your main form).
If you need to keep the floaters as UserControls, you can make the client area of your main form transparent by setting the form's TransparencyKey property to some arbitrary color (Color.Red, for example) and then setting the form's BackColor property to the same color. This will make your form transparent and able to be clicked through.
Please don't make a UI like this. It is very non-standard, and doesn't gain anything in the realm of usability. You could simplify things by keeping it all in one window like Visual Studio.