FromLogFont is extremely slow - c#

I have a simple WinForms window in which the user can modify their user settings.
Sometimes (but not always) the app appears frozen while the window takes many seconds to open.
The Form contains a single TextBox.
After profiling I found that up to 19 seconds are spent in the constructor of this textbox,
specifically in System.Drawing.Font.FromLogFont.
https://learn.microsoft.com/en-us/dotnet/api/system.drawing.font.fromlogfont?view=dotnet-plat-ext-7.0
A GDI LOGFONT, or logical font, is a structure that contains 14 properties that describe a particular font.
I have tried using a different or the default font, but the problem seems very arbitrary, sometimes the window opens in less than a second, sometimes it makes you wait for half a minute.
This is about as far as I got with profiling, what are ways to further debug this problem?
I tried using different fonts, or the default fonts. The problem is sometimes there, sometimes not.
The expected result is that the window opens seemingly instantly, not making the user wait.

Related

Strange/Unpredictable Transparent Background Bug In Winforms Application

I've been experiencing a very strange bug with a Winforms application, where showing a hidden form may result in that form's buttons & backgrounds coming up transparent. Buttons can be subsequently revealed by moving the mouse over them, as if the form hadn't been properly invalidated/drawn. For instance, a form that looks like this:
May come up like this:
Moving the mouse around causes the buttons to draw:
Here's a short video to show exactly how it behaves: http://screencast.com/t/XmFSPfLw. Explicitly calling Invalidate() or Refresh() in the Show event doesn't fix it.
What's strange is that this issue appears only on SOME computers, and I haven't been able to discern anything that those computers have in common.
I've seen it happen in different versions of Windows 7 (Embedded, x64, and x86) - but not all instances of any of those.
All systems are running the same version of .NET, and all have been fully updated.
On systems where it happens, it only happens when showing a form that'd been previously shown & hidden; it occurs when re-showing it (i.e. never the very first time the form is created & shown).
On systems where it happens, it doesn't happen for all forms, and isn't even consistent with the forms for which it happens (example of several subsequent hides/shows, sometimes it happens, sometimes it doesn't: http://screencast.com/t/liQ53p8Sce).
On systems where it happens, it only happens if the application is scaled to the full resolution of the screen. I use Control.Scale() to scale each form up to a user-specified resolution; if that's the same as the screen resolution, the bug may happen on some systems; if it's scaled up to anything less, I've never seen it happen (example: here's the same video as the first one above; with the form scaled to less than the full screen resolution, it doesn't happen: http://screencast.com/t/k87zJDeSYPGL).
I've been tearing my hair out trying to figure out what's different about the systems that exhibit the issue, and why it's happening in the first place. I literally had to have a client ship me a laptop that shows the issue, as I couldn't reproduce it on any systems I have here. I'm really at a loss as to the cause...

ElementHost size causes slow wpf open/load with high memory usage

The Problem:
We have a Winforms application, which can open up another WPF Window. This window contains various icons and text and isnt overly complex. Back to the main window, the winforms one, this also has a WPF control embedded using ElementHost(ElementHost is specifically designed to make it possible for Winforms to host a WPF Control). We have noticed however, that once the memory usage of this application get quite high, this second WPF Window can take a considerable amount of time to open.
We have made a small test application in VS2012 which is able to replicate the problem. The test application opens a Winforms window which has two buttons; "Add 4gb memory usage" and "Open WPF Window". The WPF Window has a single small icon on it(48*48) and that is all.
When we add the 4Gb memory usage and attempt to open the window for the first time, it takes around 7 seconds to open the window.
CODE: I have made the test app and source code publicly available through BitBucket.
Things we have found out:
The app is definitely running in 64-bit, as it will throw OutOfMemoryExceptions in 32-bit.
Without the memory usage the window opens immediately.
With the memory usage, the window is only slow the first time it is opened.
If the WPF window doesnt have an image, it opens immediately.
Reducing the size of the elementhost which is on the winforms control, to say 1*1, the window opens immediately. Obviously this
isn't a great solution as it doesnt show much of our WPF Control at
this size.
The ElementHost size in our application is about 1000*700, but we noticed there is a big drop off point when reducing the ElementHost
size, so it will take this 10 seconds, until it gets to around
350*350, at which point it suddenly improves to be fast again. This
could be computer dependent, or maybe a limitation of some kind.
Removing the image from the wpf window will make it fast again.
Adding new images as resources, and on the WPF window, linearly slows the open time (e.g. 1 image = 7 seconds, 2 images = 14 seconds).
Experimented with making sure the image is the same size it is being displayed at so there should be no resizing, but this didnt seem to make any difference.
Experimented with different image types, .png, .tiff, .ico but they all seemed to be slow.
Has anyone else experienced this problem / Any suggestions on what our next step could be?
After some more analysis using a profiler, this article seemed to be the same issue as what I was experiencing.
typeof(BitmapImage).Assembly.GetType("MS.Internal.MemoryPressure")
.GetField("_totalMemory", BindingFlags.NonPublic | BindingFlags.Static)
.SetValue(null, Int64.MinValue / 2);
Not the nicest solution, but it definitely fixed the problem.

Promoting a NotifyIcon from overflow area without showing a balloon tip

I'm working on a WPF/.NET 4 app that lives in the system tray and periodically shows messages to the user.
I would like to have my NotifyIcon promoted from the overflow area of the system tray to the visible portion each time there is a message. This works fine if I call 'ShowBalloonTip' on my NotifyIcon; however, I don't wish to use the standard OS balloons (I have a custom control for this, which supports multiple instances and custom animations).
Is it possible? It doesn't seem to allow showing an empty/invisible balloon, and disposing/re-adding the icon does not have the intended effect. I wonder if I should look into creating a secondary tray icon each time I have a message (like the Outlook 'new mail' icon) and removing it when my message fades away.
This is not possible. A significant problem with the notification area is that every programmer thinks that his app is important enough to be next to the clock. Modesty is not a programmer's trait and that's a good thing.
The user however sets different priorities. He's liable to run more than three apps that all think they should have the exalted location. This got really out of hand, I've seen screenshots of Win98 machines where 75% of the taskbar was covered with Important Programs.
This was not sustainable and Microsoft did something about it. They added the overflow area to provide a home for notification icons that the user doesn't think are all that important. Being a computer user myself, it is very quickly populated with whatever shovelware icons come with a new machine I purchase. From there, the rate I uninstall this stuff is inversely proportional to the number of times it balloons me with completely useless or inscrutable info. The only ones that ever really survive are the ones that never show a balloon.
A core feature of the overflow area is that programs cannot do anything to elevate themselves back next to the clock. That would completely defeat the point of having it. Other than showing a balloon, the user needs to know where it came from. That better be something meaningful and relevant to the user. If it is not then your uninstaller is the part of your product that gets tested most.
You are a computer yourself and have battled annoying notify icons too. Apply the exact same logic to your own. And don't forget to ask somebody else what they think about yours. And if your notifications are useful enough, this just takes care of itself. Your user will move it back. Because that's what he can do.

C# Project compiles quickly, but then VS becomes unresponsive

I've got a problem that's driving me nuts. We have a C# project that has a few types of custom controls, but has several hundred instances of those controls (don't ask). Every time I do anything that requires compile I get the following behavior:
The project appears to build very quickly (like 3 or 4 seconds).
Then VS becomes totally unresponsive for quite a while (maybe 15 seconds to a minute)
The status at the bottom of the window shows "Build Succeeded" during the unresponsive period.
Clicking just about anything will cause a spinner to appear.
Eventually the spinner will go away and the status will show "Ready" at the bottom, at which point I'm back in business.
I'm almost certain that this is a self-inflicted problem, but for the life of me I can't figure out what is going on during the "spinning" period. Is there any way to see what's going on during the build process so that I can determine precisely how I'm shooting myself in the foot?
UPDATE: I tried a strange experiment. I created a new application using the exact same user controls and then just plopped down about 2,000 of them on my form. No problem at all, this application works fine. How incredibly odd...
Close the form design view before compiling the project.
If that did not work (which worked for me but not for you as you've mentioned in your comment) then I think it's something about your custom control like trying to connect to a server and validating it's licensing. Check your internet traffic with something like Wireshark. I hope that helps.

Is it possible to change size of minimized window in MDI C# Winforms

Users complain that when they have several minimized windows in MDI container it's impossible to distinguish them unless they resore each. I wonder if it's possible to make minimized window a little bit wider so the text in the caption can contain 6 characters?
Thanks in advance!
No, this is not possible. Windows determines the width of a minimized window using the current system parameters, and there's no way to change this dynamically for a single application without changing the values across the entire system.
Specifically, the default size of all minimized windows is 160x31. In a MDI application, you actually get to see this size because the window is minimized into its MDI host, rather than into the Windows taskbar. Raymond Chen (a developer on the Windows Shell team at Microsoft) published a couple of blog entries a while back that explain why this particular size was chosen, and what it means. The first is available here: Why do minimized windows have an apparent size of 160x31? And the second follow-up entry can be read here: No, really, why is it 160x31? As he explains in that second post:
The width of the miniature title bar is determined by the iWidth member of MINIMIZEDMETRICS structure. You can retrieve and change this structure with the help of the SystemParametersInfo function. (Use the SPI_GETMINIMIZEDMETRICS and SPI_SETMINIMIZEDMETRICS flags, respectively.) Some people will mention the MinWidth registry value, but those people are wrong. Notice, for example, that messing with MinWidth requires a logoff cycle, whereas using SPI_SETMINIMIZEDMETRICS takes effect immediately. That's because SPI_SETMINIMIZEDMETRICS updates the internal state variables, whereas whacking the registry just change a value in a database that nobody pays attention to once you've logged on.
What about the height? That's just the height of a caption bar, which you can adjust from the Appearance tab of the Display control panel. (Programmatically, you can use that helpful SystemParametersInfo function, this time using the iCaptionHeight member of the NONCLIENTMETRICS structure.)
Since I doubt your users really want you messing with their default system parameters by P/Invoking the SystemParametersInfo function, you aren't left with a whole lot of options. My recommendation, especially if they're working with a single window at a time and leaving the others minimized, is to switch to an alternative interface. The intention of MDI was to allow users to tile or cascade multiple windows so that they could see more than one at a time. Since it sounds like that's not the typical use case, you might both be better served by switching the application to use tabs instead. This is often called a tabbed document interface (TDI), a somewhat more modern implementation of the old multiple document interface (MDI). It's become quite popular over the years; check out the Wikipedia article.
[Although this post is 11 years old, i'm trying...:
I'm facing an issue with in-app minimized windows, which are broken on my Windows11 (certainly by a software, but I don't know which one...). Those in-app minimized windows are much more narrower that it should be. Instead of having the minimized title bar containing title and 3 buttons, I can only see the close button. You said here it wasn't possible to change this size for a unique software, but I assume you know(knew) where to change it for the whole system? Here is a capture of the issue in ultraedit 1 and here in 3dsMax for example 2
To those who have the same problem as me, I found the solution:
(win+r) regedit
HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics
add the string value "MinWidth".
Change the string value named "MinWidth". Set its value using the following formula:
-15*width in pixels
For me, acceptable one was -3300
Little drawback: It also changes size of the minimized windows in the taskbar (make them much wider when there is a few of them in taskbar)

Categories