Several parts of UI are not painted - wpf

We have a very strange behaviour of a WPF application. Sometimes (not very ofen), some parts of the user interface are simply not painted.
Just recently the save button and a text box on the configuration view didn't show up. Even more strange is that after a relogin, what results in a new view instance, the problem is still present.
Sometimes it helps to hover the mouse over the position where the missing controls usually are to get them visible. But switching the tab page and then back to the original one with the missing controls they are all missing again. Other controls won't show up by hoovering the mouse over them.
Another problem is that dialogs are sometimes screwed up. Parts of the dialog are displaced vertically. But when e.g. a text box inside the dialog gets the focus, it is painted correctly while the rest of the dialog stays displaced.
I don't have the slightest clue what causes this problem. Any idea is welcome.
[Edit 1] So far we have seen this always on Windows XP. Windows 7 seems to be Ok. Also switching to Software-Rendering seems to fix the problem on Windows XP but I'm not sure on this.

The problem was solved by switching the RenderMode to SoftwareOnly. It seems to be a .NET 4 issue when running on Windows XP:
public class MyWindow : Window
{
protected void SetSoftwareRendering()
{
System.Windows.Interop.HwndSource hwndSource = PresentationSource.FromVisual( this ) as System.Windows.Interop.HwndSource;
System.Windows.Interop.HwndTarget hwndTarget = hwndSource.CompositionTarget;
hwndTarget.RenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
}
}
Alternatively one can write
System.Windows.Media.RenderOptions.ProcessRenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
All windows are inherited from MyWindow and can decide wether or not they want the software rendering. Currently we don't use this flexibility and have it enabled on all instances.

If this happens in other WPF applications too it might be your hardware, driver, OS or .NET software.
If not, the only option is to try and reproduce in a minimal case and on several machines.
Are you able to make a minimal version that has the problem en post the code?

Related

A proper solution to a WPF application using On Screen Keyboard

I´ve been working for some time on a good OSK solution for my WPF apps, that are running on a tablet. But it´s hard working with the OSK.exe and tabtip.exe, because of several bugs, strange behaviour and no standardized solution to this ordinary problem.
What I (probably) need is a custom textbox control, which inherits from System.Windows.Controls.TextBox, and overrides some methods.
The simple requirements for this textbox should be:
1. When a user clicks in a textfield, the tabtip.exe (or alike) keyboard should pop up at the bottom of the screen (default).
2. If the keyboard pops up on top of the textbox, the contentframe should scroll so that the textbox is visible.
3. When the textbox loses focus, the keyboard should close automatically, except if the user clicks on another textbox.
This seems like pretty standard behaviour right? Well I´ve looked a long time for solutions (there is no standard microsoft way which is kind of weird), and as said I´ve tried making my own but with no luck. For example, sometimes when I try to kill the process, it fails. When I click the close button in the upperright corner on the keyboard, like 5-6-7 times, it closes. The behaviour from PC to tablet is not consistent. The ScrollViewer.ScrollToVerticalOffset(x); sometimes doesent work on a tablet, and so on.
So does any of you know a good solution to this common problem?

MFC: how to render an Aero-style combo box for owner draw?

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.

WPF User Control On MFC Dialog Showing Hidden Every Once and a While

I am running into a very strange problem that I wanted to see if anyone else has seen. I have a C++ application (compile with CLR support) that has a MFC dialog which hosts a WPF user control. Every once and a while, the WPF user control will not appear when the dialog opens. The control is there as I can press a button on that user control. Obviously, I cannot see it, but the button still responds to a click event if I click the area where the button is supposed to be.
The strange part in all this is how sporadic it happens. Sometimes it happens the first time the user goes into the dialog after starting the application. Other times, it will happen after successfully going into the dialog a few times. We have deinitely not found any pattern to when it will happen. It just happens once and a while. Also, we have seen this across all different operating systems - XP, Vista and Win7.
To correct the problem, simply closing the application and relaunching it norally cures it.
In terms of the code, the standard approach for WPF user controls on MFC dialogs is being used:
// Create the initial object
System::Windows::Interop::HwndSourceParameters^ sourceParams = gcnew System::Windows::Interop::HwndSourceParameters ("BatchSelectionContainer");
sourceParams->PositionX = x;
sourceParams->PositionY = y;
sourceParams->Height = height;
sourceParams->Width = width;
sourceParams->ParentWindow = System::IntPtr(parent);
sourceParams->WindowStyle = WS_VISIBLE | WS_CHILD;
BatchSelectionDialogGlobals::gHwndSource = gcnew System::Windows::Interop::HwndSource(*sourceParams);
BatchSelectionDialogGlobals::gHwndSource->AddHook(gcnew HwndSourceHook(ChildHwndSourceHook));
// Save a reference to the new frame
BatchSelectionDialogGlobals::BatchSelectionFrame = gcnew ProteinSimple::ParticleDetection::Console::BatchSelection();
// Establish an event handler for the buttons
BatchSelectionDialogGlobals::BatchSelectionFrame->EnableExecuteButton += gcnew ProteinSimple::ParticleDetection::Console::BatchSelection::GeneralHandler(&BatchSelectionDialog::EnableExecuteButton);
BatchSelectionDialogGlobals::BatchSelectionFrame->DisableExecuteButton += gcnew ProteinSimple::ParticleDetection::Console::BatchSelection::GeneralHandler(&BatchSelectionDialog::DisableExecuteButton);
// Finalize the visual parts and return the handle
BatchSelectionDialogGlobals::gHwndSource->RootVisual = BatchSelectionDialogGlobals::BatchSelectionFrame;
return (HWND) BatchSelectionDialogGlobals::gHwndSource->Handle.ToPointer();
This is certainly a strange one. I have some of my users that have never seen it, while others it happens many times a day.
It feels like a bug in MFC in how it displays the WPF control. However, I have searched on-line and have never heard anybody describe this problem. The code is not throwing any exceptions, so I am not sure what the problem could be.
I am stumped and would appreciate any insight into the problem.
WPF doesn't draw the stuff as windows-controls as MFC or WinForms do draw - you can check it using Spy++. That's why its not possible/easy to mix WPF and MFC.

Weird scrollbar UI in hosted WPF composite control

My windows forms application hosts AvalonEdit (the composite WPF control in question) in one of its forms to cater to its text editing requirements. Here's the code I use:
WPFHost = gcnew ElementHost();
TextField = gcnew AvalonEdit::TextEditor();
WPFHost->Dock = DockStyle::Fill;
WPFHost->Child = TextField;
TextField->Options->AllowScrollBelowDocument = false;
TextField->Options->EnableEmailHyperlinks = false;
TextField->Options->EnableHyperlinks = true;
TextField->Options->RequireControlModifierForHyperlinkClick = true;
TextField->ShowLineNumbers = true;
ContainerControl->Controls->Add(WPFHost); // the container is a panel
The code compiles and executes fine, except for the scrollbars - http://dl.dropbox.com/u/2584752/avalonEditBug.png . Right clicking on what's left of the bar raises an ArgumentOutOfRange exception.
Strangely, I wasn't able to reproduce the issue when I tried hosting the control in a newly created sample project. 'mI using the latest build of the text editor and have all the requisite assemblies installed.
EDIT: Wrapping the editor in a usercontrol doesn't help either.
You say that the control works fine in a new/blank project but fails in the one you need makes me wonder about conflicts more than anything. In the project you're really wanting compared to the project it worked in what are the differences? .NET version? Referencing an assembly from a directory in one but out of the GAC in another?
It's hard to say that the control is messing up for you when you've got it working elsewhere, so the only thing I can suggest is just dive deep into the differences of the two projects.
Good luck.
This looks like a layout error to me. Maybe WPFHost measures the TextField unexpectedly.
I can suggest setting specific Width and Height on the TextField itself. If this fixes the problem you can adjust those as the size of the WPFHost control changes or try setting the MaxHeight/Width, sometimes they help and save some code for Width/Height updates.
try to create a WPF grid as a child of ElementHost, and place the editor inside that grid. On Other way, is to create an UserControl have the editor in that control and use the control inside your Winform app. Such approach helped me a couple of times.
I've implemented a workaround for the issue as mentioned in this thread [ Synchronizing a WPF ScrollViewer with a WinForms ScrollBar ].

What causes a window to not appear in the taskbar until it's Alt-Tabbed to in Vista?

When our app is started programatically (either through custom action in MSI installer or when starting a new instance) in Windows Vista (also happens in Windows 7 Beta) it won't appear in the taskbar and isn't focused. Alt-tabbing to it will make it appear in the taskbar properly and stay there.
What causes this? I've seen this in some other apps before as well, but not sure why. Out app is .NET WinForms app. Never see this happen in XP, only Vista and 7
Edit: Well, it seems like the only time this happens reproducibly is when it's run by the installer, I believe there's other times it occurs, but I might just be crazy. The launching code is a bit complex to post because we handle various command line launch parameters and it launches a signin form before actually launching the main app etc.
Has anyone had to deal with this scenario before and worked it out?
Try checking your main application form "Form Border" property.
If it's ToolWindow (Fixed or Sizable), try changing it to FixedDialog for example.
This solved the problem in my case.
The usual reason for this is that your main application window doesn't have the window styles that let Windows know it's a main application window (rather than a tool window or a dialog box). So Windows is having to guess based on how the app was started, etc.
Use Spy++ to complare the window styles (especially extended styles) if your window to that of some other window that doesn't have this problem. Are you missing the WS_EX_APPWINDOW style? Are any other styles/extended styles different from other top level windows?
G.So's answer made me find the solution for my problem, wich was caused by the fact that i had my form sizable from launch, but set to borderless in the load void.
If anyone is interested in how i managed to keep the switch to borderless and have it pop up as it should in the taskbar without any dirty hacks.. here it is..
Make a new event from the form on the form's "Shown" event, and put your line of code for switching to borderless in here. Problem solved :)
private void Form1_Shown(object sender, EventArgs e)
{
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
}
and for the lazy ones ;) >>>>
this.Shown += new EventHandler(Form1_Shown);
Thanks again G.So for clearing up what could cause this in the first place.
I stuggled with this issue as well, and found like a previous commenter said, you cannot have anything in the form's Load() event that changes that FormBorderStyle property. Move anything that changes it to the Shown() event.
Well, one solution is to use a hack like this. That's really not what it's for.
Usually the decision of whether a window will be in the taskbar or not is based on the border styles it uses. The article I linked to provides a bit more detail. The article's comment about the window having an owner or not is quite possible highly relevant to your issue, since the window might somehow be getting a different owner when launched by the installer.
That article is in VB but it's all based around API calls so the info it provides is pretty language independent.
Never see this happen in XP, only Vista and 7
Maybe it's a bug in Vista...?
What happens if you call SetForegroundWindow() (or equivalent in .Net)?
Edit
I did of course mean "BringWindowToTop()".
Or do both.
We had this same problem and fixed it by setting the form property showintaskbar property to true.
Weird that all windows os's dont run apps in the same way!
In our situation, this was tracked down to the form's text property being changed within the Load event.
After putting this inside a BeginInvoke, this odd behaviour no longer happened.
Hope this helps anyone else.
Example
private void Form_Load(object sender, EventArgs e)
{
...
...
...
// this needs to be inside a BeginInvoke otherwise it messes with the taskbar visibility
this.BeginInvoke(new Action(() =>
{
this.Text = "Something new";
}));
...
...
...
}
We encountered the same issue, also in Windows 8. Sometimes the form was receiving correctly the focus, but say just ~30% of the time.
We tried different solutions, but actually the one that worked was the following:
private void OnFormShown(object sender, EventArgs e)
{
// Tell Windows that the Form is a main application window
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
// Even if true, enforce the fact that we will the application on the taskbar
this.ShowInTaskbar = true;
// Put the window to the front and than back
this.BringToFront();
this.TopMost = true;
this.TopMost = false;
// 'Steal' the focus.
this.Activate();
}
Moreover, we ensure also not to set the title of the form during the Load event.

Resources