I have a very simple WPF user control that is mixed in with a windows forms app. It has a list box that renders its scroll bar without the thumb (image below). I narrowed it down to a plugin in my app that uses Managed DirectX (MDX). If I remove the plugin, the scroll bar is just fine. I know MDX is deprecated, but I don't think today is the day to consider an upgrade. Has anyone ever seen their scroll bar get messed up, or has any idea what I should do?
And I should add, that this control also lives in a plugin. There is no way for the 2 plugins to reference each other.
<UserControl x:Class="MAAD.Plugins.Experiment.Visual.TestEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="403" Width="377">
<ListBox Margin="12" Name="listBox1" />
</UserControl>
Update: You can read about the solution below.
As it turns out, I stumbled on the solution today while working with a client. If you add the CreateFlags.FpuPreserve flag to your device creation, the scrollbar should go back to normal.
I've seen this bug too. It is not a SlimDX issue per se, but rather due to DirectX using 32-bit math on the x87 FP stack.
Use the FpuPreserve flag when initializing your device and the problem should go away.
My suggestion is to get rid of your MDX plugin.
I've used both WPF and MDX, though not in the same project. Both libraries talk to DirectX and ultimately will store state at the native level, which can cause problems. With WPF I've had rendering issues related to my video drivers and the fix was to upgrade the video driver to a newer version.
Initializing DirectX can affect the ways DirectX (and your CPU!) performs for your whole application . For example, when you initialize MDX by default it will set the CPU to do all floating point calculations in single precision, for the whole process, regardless of how you declare your original value. As you might imagine this lead to a lot of head scratching for a long time as to why we were getting different results in the application and our unit tests.
I suspect that when MDX is initializing it is enabling, or disabling some feature or setting in your graphics card (or possibly some software setting) that is affecting the WPF pipeline somehow.
I wish I could be more helpful. Good Luck.
I had this problem as well. As mpg found, adding the D3DCREATE_FPU_PRESERVE flag to the device creation will fix it. if anyone is wondering what the code looks like:
d3d->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
(HWND)this->Handle.ToPointer(),
D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_FPU_PRESERVE,
&d3dpp,
p);
Have you tried SlimDX instead of MDX? SlimDX is a newer wrapper around DX and is actively under development. Perhaps you could do in SlimDX the same thing you use your MDX-Plugin for and the scrollbar functions normally again.
Peter is right about the interaction of WPF and MDX. WPF uses DirectX internally. So changing settings in MDX (or SlimDX) can change how WPF behaves. You could also try to take a look at the code of the WPF scrollbar (for example with the .NET Reflector, IDA, whatever you need) and check the settings the Scrollbar relies on.
Are you on Vista? We've seen a lot of SlimDX/WPF simply vanish by creating a Direct3D9Ex device instead of a normal one when running under Vista targets.
I took everyone's advice and ported my app to SlimDX. It wasn't too bad (almost every class/method/field is named exactly the same in SlimDX as MDX). Unfortunately, I still had the same issue. I was able to simplify Both SlimDX and MDX down to the following app:
public partial class MainForm : Form
{
Direct3D Direct3D = new Direct3D();
Panel slimPanel = new Panel();
public MainForm()
{
InitializeComponent();
CreateDevice();
BuildWindows();
}
void BuildWindows()
{
var listBox = new System.Windows.Controls.ListBox();
listBox.ItemsSource = Enumerable.Range(0, 100);
var elementHost = new ElementHost();
elementHost.Child = listBox;
elementHost.Dock = DockStyle.Fill;
Controls.Add(elementHost);
slimPanel.Dock = DockStyle.Left;
Controls.Add(slimPanel);
}
void CreateDevice()
{
PresentParameters presentParams = new PresentParameters();
presentParams.BackBufferHeight = slimPanel.ClientRectangle.Height;
presentParams.BackBufferWidth = slimPanel.ClientRectangle.Width;
presentParams.DeviceWindowHandle = slimPanel.Handle;
var device = new Device(Direct3D, 0, DeviceType.Hardware, slimPanel.Handle, CreateFlags.HardwareVertexProcessing, presentParams);
}
}
The scroll bar won't show. I was able to get the scrollbar to show if I made sure the listbox got to paint before the Device was created.
The final solution was to add a WPF ListBox to my form in the constructor then delete it after the form finishes loading. I'm not sure if this is a bug in WPF or DirectX, I might try submitting a bug with Microsoft.
BTW, I can't get XNA to cause this issue.
I'd second the reservations of the previous posters regarding MDX in the context of WPF. One shot into the dark though:
Have you tried targeting your control for .NET Framework 3.5 SP1 already? There has been significant work regarding DirectX/Direct3D interoperability and performance, see for example:
Paragraph 'Graphics Enhancements' in What's New in .NET Framework 3.5 Service Pack 1
Paragraph 'WPF Interoperability with Direct3D' in What's New in .NET Framework 3.5 Service Pack 1
Some of those enhancements might eventually yield positive side effects regarding your problem.
Related
I've been writing a custom drawn tab control for a few days now and for the most part everything is pretty and it does an amazing job ... except when I use it on my Windows 10 computer (at run-time).
I've gone back to the most basic few lines of code to trace the error and I can't for the life of me figure this out.
Below is the only code being used, in a nutshell I'm designing a horizontal aligned tab control.
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1.UI
{
class TabControlTest : TabControl
{
public TabControlTest()
{
Alignment = TabAlignment.Left;
SizeMode = TabSizeMode.Fixed;
}
}
}
I've simply added the custom tab control to the form, added a couple of group boxes for reference purposes and changed the background colour of the form to grey so you can clearly see the tab control.
Now, at design time the 2 group boxes (1 in the tab control, 1 on the form) align perfectly.
But at run-time I see a very different result.
As you can see the tab part of the control is now larger than it was at design time and the resulting change means the contexts of the tab have also moved.
If I do this on a Windows 7 computer everything is displayed as it appears at design time, as it should!
I've added ImageSize but it makes no difference.
ItemSize = new System.Drawing.Size(30, 150);
I've reinstalled VS on my (Win10) development machine. I'm at a loss to explain why and how to resolve this.
Any/all help would be immensely appreciated.
Looking at your tab width in your comparison images, I believe this is another issue caused by automatic Windows control scaling. I found that it is the dpiAware option is automatically set when it's run from within Visual Studio and then reverts back to the default Windows Scaling that windows Implements when outside Visual Studio.
To prevent that auto-scaling when run outside Visual Studio altogether you need to Notify the OS that you're application is dpiAware by calling the Win32 P/Invoke SetProcessDPIAware() method from within your Main() before Application.Run() is called, like the example below demonstrates. This will let your controls use the native resolution which your designing the coordinates from.
static class Program
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
static void Main(string[] args)
{
if (Environment.OSVersion.Version.Major >= 6)
SetProcessDPIAware();
Application.Run(new UIMonitor());
}
}
Alternatively, if you want to keep the scaling, you may be able to set the GroupBox location based off the Width of the Tab Control instead of a specific location. (Or by using some combination of Control measurements instead of exact picel placement.)
I need to knock out a quick animation in C#/Windows Forms for a Halloween display. Just some 2D shapes moving about on a solid background. Since this is just a quick one-off project I really don't want to install and learn an entire new set of tools for this. (DirectX dev kits, Silverlight, Flash, etc..) I also have to install this on multiple computers so anything beyond the basic .Net framework (2.0) would be a pain in the arse.
For tools I've got VS2k8, 25 years of development experience, a wheelbarrow, holocaust cloak, and about 2 days to knock this out. I haven't done animation since using assembler on my Atari 130XE (hooray for page flipping and player/missile graphics!)
Advice? Here's some of the things I'd like to know:
I can draw on any empty widget (like a panel) by fiddling with it's OnPaint handler, right? That's how I'd draw a custom widget. Is there a better technique than this?
Is there a page-flipping technique for this kind of thing in Windows Forms? I'm not looking for a high frame rate, just as little flicker/drawing as necessary.
Thanks.
Post Mortem Edit ... "a couple of coding days later"
Well, the project is done. The links below came in handy although a couple of them were 404. (I wish SO would allow more than one reply to be marked "correct"). The biggest problem I had to overcome was flickering, and a persistent bug when I tried to draw on the form directly.
Using the OnPaint event for the Form: bad idea. I never got that to work; lots of mysterious errors (stack overflows, or ArgumentNullExceptions). I wound up using a panel sized to fill the form and that worked fine.
Using the OnPaint method is slow anyway. Somewhere online I read that building the PaintEventArgs was slow, and they weren't kidding. Lots of flickering went away when I abandoned this. Skip the OnPaint/Invalidate() and just paint it yourself.
Setting all of the "double buffering" options on the form still left some flicker that had to be fixed. (And I found conflicting docs that said "set them on the control" and "set them on the form". Well controls don't have a .SetStyle() method.) I haven't tested without them, so they might be doing something (this is the form):
this.SetStyle(ControlStyles.UserPaint, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
So the workhorse of the code wound up looking like (pf is the panel control):
void PaintPlayField()
{
Bitmap bufl = new Bitmap(pf.Width, pf.Height);
using (Graphics g = Graphics.FromImage(bufl))
{
g.FillRectangle(Brushes.Black, new Rectangle(0, 0, pf.Width, pf.Height));
DrawItems(g);
DrawMoreItems(g);
pf.CreateGraphics().DrawImageUnscaled(bufl, 0, 0);
}
}
And I just called PaintPlayField from the inside of my Timer loop. No flicker at all.
Set off a timer at your desired frame rate. At each timer firing twiddle the internal representation of the shapes on the screen (your model) per the animation motion you want to achieve, then call Invalidate(true). Inside the OnPaint just draw the model on the screen.
Oh yeah, and you probably want to turn Double Buffering on (this is like automatic page flipping).
2d Game Primer
Timer Based Animation
Both of these give good examples of animation. The code is fairly straightforward. i used these when I needed to do a quick animation for my son.
In the software products I'm currently working on, we have several 3D View controls. Appeared the need to have overlay information on top of these 3D Views. I won't go into too much background details, because it is not the point, but here are the constraints we face :
we must use two different 3D View controls
we don't have the source code for them
they are embedded in Windows Forms controls, and all our own GUIs around these controls are in Windows Forms
we use .NET Framework 3.5SP1 and Windows 7
We want to be able to display various overlay informations and controls on top of these 3D views, because we usually demo our products by showing full screen 3D views on big screens, and not show our GUIs, which have the necessary information and controls.
Back in the days we used only one type of 3D view, I managed, via various hacks involving reflection, to hook my own overlay window system written in DirectX (based on WorldWind .NET overlay widgets, the 3D view was indeed based on WorldWind at the time). The next version of the 3D View product made huge changes to the rendering core code and of course made these hacks incompatible (yeah, I had it coming, I know :-)). Moreover, we are now using, because of different needs in other products, another type of 3D View, closed source as well.
I emphasize the fact that we don't have the source code for them because we can't have access to the rendering loop and therefore cannot hook a windowing system made for 3D Engines, such as CEGUI (search for it yourself, I'm not allowed to post much hyperlinks yet, sorry).
Consequently, I had the following idea : since our 3D Views are embedded in winforms controls, why don't we code our overlay controls in plain winforms, and overlay it on top of the 3D views? The advantages of this solution are huge :
this would be compatible with both 3D Views, enabling us to reuse overlays across engines, if needed
we would be able to reuse custom controls or forms we already developed for the rest of the GUI. Indeed, it is a pretty big project, and we are beginning to have quite a library of such controls.
The only slight (!) problem is that we want to be able to manage overlay transluency, like I did with my former system in DirectX. We can't afford fully opaque overlays, because it would clutter the view too much. Imagine something like a barely visible overlay, becoming more opaque when the mouse is hovering over it for example.
Windows offer the possibility to have child windows inside other windows or controls (Win32 API doesn't really make a difference between windows and controls, this is pretty much a MFC/WinForms abstraction as I understood it), but since it is not top-level windows, we cannot adjust the transluency of these, so this is not something we can use. I saw here, that this is however possible on Windows 8, but switching to windows 8 is not possible anytime soon, because our software is deployed on quite a few machines, running 7.
So I started an intense googling session on how could I work around such a problem. It appears I must "enslave" top level windows to my 3D View controls. I already tried out something like that directly in winforms, having a form owned (not parented, there is a clear distinction, read about it in the previously linked MS page) by a control, and "following" its movements on screen. As expected, it kind of worked, but the issues are difficult to overcome. The most important is a clipping issue. If the parent form of the owner control changes its size, the overlay form is still shown in full. In my sample, I have a simple form with a menu, and a black panel containing a calendar (to show clipping differences between child controls and owned ones). I "enslaved" a borderless form containing a property grid to the black panel. It successfully follows the forms movements, but if I shrink the main form, I get this :
Clipping issue screenshot
Note how the calendar is clipped correctly (child window), and the overlay is not (owned window). I also get weird effects when minimizing/restoring the main form. Indeed, my overlay disappears when minimizing, but when restoring, it just "spawns" while the restoring animation of the main form is occuring. But this is less of an issue, and I guess can be worked around by handling proper events (but which ones?).
From what I understood, I must handle at least some of the clipping myself, using win32 API calls and hooks. I already begun to document myself, but it is quite complicated stuff. The Win32 API being a real mess, and myself being a former Unix developer introduced to Windows programming via the great .NET framework, I don't have any real experience in Win32, and therefore don't really know where to begin, and how to make myself a path in this jungle...
So if a winapi guru is passing by, or if someone has some other idea to achieve my goals given the constraints above, I'll be glad to read about it :-)
Thanks in advance, and apologies for being such a stackoverflow "leecher" by subscribing only to ask a question, but I don't have no direct internet access on my workstation (yeah, for real, I have to go to a specific computer for this), so participating in this great community is not that easy for me.
Finally, here is my sample code (designer code available if you ask) :
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
Point _myLoc;
private void formToolStripMenuItem_Click(object sender, EventArgs e)
{
var ctrl = new PropertyGrid();
var obj = this.panel1;
ctrl.SelectedObject = obj;
var form = new Form();
ctrl.Dock = DockStyle.Fill;
form.Controls.Add(ctrl);
form.Opacity = 0.7;
var rect = obj.RectangleToScreen(obj.DisplayRectangle);
form.StartPosition = FormStartPosition.Manual;
form.Location = new Point(rect.Left + 10, rect.Top + 10);
var parentForm = this;
_myLoc = parentForm.Location;
form.FormBorderStyle = FormBorderStyle.None;
parentForm.LocationChanged += (s, ee) => {
int deltaX = parentForm.Location.X - _myLoc.X;
int deltaY = parentForm.Location.Y - _myLoc.Y;
var loc = form.Location;
form.Location = new Point(loc.X + deltaX, loc.Y + deltaY);
_myLoc = parentForm.Location;
};
form.Show(this.panel1);
}
}
Clipping can be easily implemented using Region property. Each window can have an associated Region object, which defines window rendering constraints:
static void ManualClipping(Control clipRegionSource, Form formToClip)
{
var rect = clipRegionSource.DisplayRectangle;
rect = clipRegionSource.RectangleToScreen(rect);
rect = formToClip.RectangleToClient(rect);
rect = Rectangle.Intersect(rect, formToClip.ClientRectangle);
if(rect == formToClip.ClientRectangle)
{
formToClip.Region = null;
}
else
{
formToClip.Region = new Region(rect);
}
}
usage:
/* ... */
parentForm.SizeChanged += (s, ee) => ManualClipping(panel1, form);
form.Show(this.panel1);
For a .NET (Winforms) application are there any flip clock controls?
Ideally it would look something like the one found on the BlackBerry Bold:
alt text http://images.crackberry.com/files/u3/reviewimages/blackberry9000c/lgclock3.jpg
UPDATE 1:
Following this SO link I have added an element host to my project to host the WPF retroclock that #Shane mentioned.
UPDATE 2:
A few steps that I followed:
Compile RetroClock
Add DLL reference to WinForm App
Add 'using WPFControls.Clocks;'
Add 'elementHost' to Form
In Form Load event add:
//create retroclock
RetroClock rc = new RetroClock();
//add retroclock to element host
elementHost1.Child = rc;
UPDATE 3:
Styling the clock
//style clock
rc.Height = 30;
rc.IncludeLeadingZero = true;
rc.IsAmPmVisible = true;
rc.FontSize = 60;
rc.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
rc.TimeFormat = TimeFormats.Hour12;
Going along with Joel's answer, there's a simple one for WPF here.
That would be a little out of place for winforms, the main point of which is to expose the common controls to .Net to help developers build windows applications that use the "standard" look and feel. This doesn't mean you won't find one, but that you should think 3rd party first here. Anything provided by Microsoft is going to be at best an afterthought.
WPF, on the other hand, is a much better fit for this kind of thing.
It's pretty easy to make one yourself. Add a class, derive it from Control. You'll need a Timer that keeps it going, have its Tick method call Invalidate(). Override OnPaint() to draw the digits and am/pm indicator. You'll want the TextRenderer.DrawText() overload that draws inside a rectangle to get the digits centered. Draw a black line through the center.
Ought to be fun.
I am an inexperienced programmer , completely new to programming for windows .
I am writing a little program that I always wanted . Its being written using C# using .net framework. atleast thats what I think I am doing. All the talk about framework and .nets , windows forms , and win32 api has all got me really confused.. :(
anyways I have simple Form object.
Form f = new Form() ;
f.Text = "" ;
f.ControlBox =false ;
Now How to remove the all the borders on the form except one sides? As in, the side borders should go , but the top border should stay
FormBorderStyle doesn't have anything for this
Also how do you people solve such problems yourself , without asking ? look at others code ? read a a book ? any particular website ?
I have googled , but it didn't turn up nothing.
Gidday,
This is impossible, unfortunately - you can remove the whole border, though, and then draw your own on the form and use OnMouseDown, OnMouseUp and OnMouseMove to do your own dragging...
To solve such a problem myself, I would look at various different ways of verbally representing the problem (eg. "borderless form", "custom borders on winform", etc) and spend a bit of time Googling for it. As my boss wisely says, productivity isn't always about how much code you cut, it's also about what you can learn.
EDIT: As the popular expression goes, "Google knows all" - chances are that, if you spend a bit of time googling and you still can't find anything, then it probably hasn't been solved, or it's very very rare. Another way would be to invest in a few good books, e.g. Windows Forms programming (or even just Windows programming - it's incredibly useful to know about the underlying mechanics of Windows, and things like that are what help turn you into a great developer. A great programmer is good at coding, but a great developer is good at actually building useful software. :)
I assume you've tried FormBorderStyle.FixedSingle? This would display a form with a border at the top only.
Anyway, if that isn't the case you can set the forms Region.
Something like...
public static void HideBorders(Form form)
{
Rectangle newRegion = form.Bounds;
Rectangle formArea = form.Bounds;
Rectangle clientArea = form.RectangleToScreen(form.ClientRectangle);
formArea.Offset(form.Location);
newRegion.Offset(clientArea.X - formArea.X, 0);
newRegion.Width = clientArea.Width;
newRegion.Height = (clientArea.Y - formArea.Y) + clientArea.Height;
form.Region = new Region(newRegion);
}
As for how do you know what to do? All of the things you mentioned, help files, web forums, books. The main thing is practice, practice, practice. The more you do something the better you should become.
I don't think it's actually possible to do exactly what you describe, since the .NET Framework is just going to delegate the drawing of your Form's border and title bar to Windows itself, which doesn't have any option for what you describe AFAIK.
Instead, what I would do is use FormBorderStyle.None and then draw any window decorations (title bar, borders) you want manually.
A Google search for "borderless form C#" turns up these sites as the top three hits:
BorderLess Window (java2s.com)
Transparent borderless forms in C# (c-sharpcorner.com)
Draggable Form: Drag a Borderless Form by Clicking Anywhere on the Form (codeproject.com)