Problems with PrimaryScreen.Size - c#

I've been fine with Screen.PrimaryScreen.Bounds.Size for some time, but on my Windows7 computer attached to my big-screen TV it is giving me incorrect values.
I read elsewhere to try SystemInformation.PrimaryMonitorSize but that gives the same values.
When I right click the desktop to get Screen Resolution, it says 1920x1080. The above two are giving me 1280x720.
I've also tried the WPF versions:
var w = System.Windows.SystemParameters.PrimaryScreenWidth;
var h = System.Windows.SystemParameters.PrimaryScreenHeight;
MessageBox.Show(new Size((int)w, (int)h).ToString());
The display size has been changed via the (right click the desktop) Personalize > Desktop options to be 150% (since the screen is 60" and you sit kind of far away).
How to detect this so the value's returned from the above can be adjusted?
Note: I've discovered how to get around this with a right-click executable and adjust the compatability to disable DPI virtualization, but I still need a programatic solution so I don't have to have user's adjust this themselves: See - http://msdn.microsoft.com/en-us/library/dd464660(VS.85).aspx#dpi_virtualization

It could be your Dpi setting in windows set above 100%
Try using this method, this will scale the resolution to the current system Dpi settings
Winforms:
private Size GetDpiSafeResolution()
{
using (Graphics graphics = this.CreateGraphics())
{
return new Size((Screen.PrimaryScreen.Bounds.Width * (int)graphics.DpiX) / 96
, (Screen.PrimaryScreen.Bounds.Height * (int)graphics.DpiY) / 96);
}
}
WPF:
private Size GetDpiSafeResolution()
{
PresentationSource _presentationSource = PresentationSource.FromVisual(Application.Current.MainWindow);
Matrix matix = _presentationSource.CompositionTarget.TransformToDevice;
return new System.Windows.Size(
System.Windows.SystemParameters.PrimaryScreenWidth * matix.M22,
System.Windows.SystemParameters.PrimaryScreenHeight * matix.M11);
}
Note: Make sure your MainWindow is loaded before running this code

I don't feel this is a duplicate question, but the answer is the same as on another thread: https://stackoverflow.com/a/13228495/353147 As the question isn't about blurry fonts but why Screen.PrimaryScreen.Bounds.Size returns faulty information. It could help others.
I did run into an error message, that mscorlib threw an null error. From this thread http://forums.asp.net/t/1653876.aspx/1 I was able to discover that unchecking "Enable ClickOnce security settings" fixed it. This seems like a hack, but it works.

Related

Aspect ratio of video is maintained on one computer but not the other with DirectShow

I have a C# application which plays videos using the DirectShowNet library. When I debug my application using Visual C# on my laptop, the video is stretched to fit the container's dimensions i.e. the aspect ratio of the video is not maintained. When I load and run my application on a different computer (same operating system), the aspect ratio is maintained and black bars are created on the screen.
I do not want the aspect ratio to be maintained. I want the other computer to display the video the same way my computer is displaying it.
Why do you think the two computer's act differently and/or how do I fix this?
When I first saw this behaviour on the other computer, I updated that computer's DirectX to no avail. The exact same videos are being run on both systems.
EDIT #1: Could it possibly be some missing filter on the other computer? I assumed the default behaviour of DirectShow was not to maintain the Aspect Ratio.
EDIT #2: When I attempted to use IVMRWindowlessControl (VMR-7 & VMR-9), the cast from the VMR to the IVMRWindowlessControl kept on resulting in a NULL variable. As a result I tried IVMRAspectRatioControl with VMR-7 and it worked on one of the computers. The other computer stayed in Letterbox mode despite the call to remove the Aspect Ratio preservation.
EDIT #3: Here is the code using IVMRAspectRatioControl with VMR-7:
int hr = 0;
this.graphBuilder = (IGraphBuilder)new FilterGraph();
this.vmr = new VideoMixingRenderer();
this.graphBuilder.AddFilter((IBaseFilter)vmr, "VMR");
this.aspectRatioControl = (IVMRAspectRatioControl)this.vmr;
hr = this.aspectRatioControl.SetAspectRatioMode(VMRAspectRatioMode.None);
DsError.ThrowExceptionForHR(hr);
hr = this.graphBuilder.RenderFile(filename, null);
DsError.ThrowExceptionForHR(hr);
I am then using IVideoWindow to display the video.
When attempting to use the IVMRWindowlessControl9, the this.windowlessControl evaluated to NULL after the cast on the 4th line. I get the same NULL error when I tried it with VMR-7. The following uses VMR-9:
this.graphBuilder = (IGraphBuilder)new FilterGraph();
this.vmr = new VideoMixingRenderer9();
this.graphBuilder.AddFilter((IBaseFilter)vmr, "VMR");
this.filterConfig = (IVMRFilterConfig9)vmr;
hr = this.filterConfig.SetNumberOfStreams(1);
DsError.ThrowExceptionForHR(hr);
hr = this.filterConfig.SetRenderingMode(VMR9Mode.Windowless);
DsError.ThrowExceptionForHR(hr);
this.windowlessControl = (IVMRWindowlessControl9)this.vmr;
hr = this.windowlessControl.SetAspectRatioMode(VMR9AspectRatioMode.None);
DsError.ThrowExceptionForHR(hr);
hr = this.graphBuilder.RenderFile(filename, null);
DsError.ThrowExceptionForHR(hr);
I'm not entirely sure how it works, but could it be possible that the second computer does not support VMR-7 for the IVMRAspectRatioControl? The operating systems on both computers are the same, however the first computer (which works) is where I'm writing the software (it has the IDE). The second computer had a fresh install of Windows. On the second computer, I also updated DirectX as mentioned earlier.
Video renderers can be configured to preserve or not preserve aspect ratio. Configuration method (and, perhaps, default setting, which can also depend on internal mode of the renderer such as overlay/offscreen surface) is dependent on video renderer version you are using, e.g. for VMR-7 you will use IVMRWindowlessControl::SetAspectRatioMode's (or, IVMRAspectRatioControl::SetAspectRatioMode if your VMR is in windowed mode) DirectShow.NET equivalent/wrapper. VMR-9, EVR has similar methods.
With VMR-9 you will use IVMRAspectRatioControl9::SetAspectRatioMode. With EVR it is IMFVideoDisplayControl::SetAspectRatioMode.
If you don't want any letterboxing and aspect ration preservation, you just disable it explicitly when you set the video renderer up.

changing screen orientation programmatically in mirror mode windows 7

How to change screen orientation of each screen individually from C++ or C#? Having dual screen display configuration in mirror mode.
Intel Graphics card is installed on the machine. I tried EnumDisplaySettings function and DeviceMode structure. However, it only works in extended mode. If I try to change orientation by this function in mirror mode both screens are set to the same orientation. Maybe there is a way to change this settings through Intel driver SDK or any other native windows 7 functionality?
UPDATE 1:
Here is the code I tried with CCD API. It still rotates both displays =(
UINT32 PathArraySize = 0;
UINT32 ModeArraySize = 0;
DISPLAYCONFIG_PATH_INFO* PathArray;
DISPLAYCONFIG_MODE_INFO* ModeArray;
DISPLAYCONFIG_TOPOLOGY_ID CurrentTopology;
SetDisplayConfig(0,NULL,0,NULL,SDC_TOPOLOGY_CLONE|SDC_APPLY); //set to clone mode
GetDisplayConfigBufferSizes(QDC_ALL_PATHS, &PathArraySize, &ModeArraySize);
PathArray = (DISPLAYCONFIG_PATH_INFO*)malloc(PathArraySize * sizeof(DISPLAYCONFIG_PATH_INFO));
memset(PathArray, 0, PathArraySize * sizeof(DISPLAYCONFIG_PATH_INFO));
ModeArray = (DISPLAYCONFIG_MODE_INFO*)malloc(ModeArraySize * sizeof(DISPLAYCONFIG_MODE_INFO));
memset(ModeArray, 0, ModeArraySize * sizeof(DISPLAYCONFIG_MODE_INFO));
LONG ret = QueryDisplayConfig(QDC_DATABASE_CURRENT,&PathArraySize, PathArray, &ModeArraySize, ModeArray, &CurrentTopology);
PathArray++;
PathArray->targetInfo.rotation = DISPLAYCONFIG_ROTATION_ROTATE180; //set Second display rotated 180
PathArray--;
SetDisplayConfig(PathArraySize,PathArray,ModeArraySize,ModeArray, SDC_APPLY | SDC_SAVE_TO_DATABASE | SDC_ALLOW_CHANGES | SDC_USE_SUPPLIED_DISPLAY_CONFIG); //apply rotation
free(PathArray);
free(ModeArray);
You can try using the CCD APIs. These functions allows you to manipulate the VidPN topology for your current session. They aren't the easiest functions to call though.
Edit:
I don't see anything wrong with your code, apart from maybe the SDC_ALLOW_CHANGES flag. I tried your code on my system which has a Nvidia card. It does one of two things depends on which target I rotate. If I rotate the 2nd of the two targets, it ignores the change. In the Nvidia control panel, I can see the 2nd monitor is rotated, but its settings are greyed out. This suggests to me that the Nvidia driver doesn't support what you want to do. If I rotate the first target, it causes both targets to rotate. I've also tried changing the target scaling to DISPLAYCONFIG_SCALING_STRETCHED. That also made no difference. SetDisplayConfig returns 0. Windows at least seems to be happy with the change.
Have you tried to do what you want with the Intel display utility? If you can't do it with the Intel tool, then maybe the Intel driver doesn't support it. You probably want to ask someone from Intel on whether it is supported.

Form.Location must be set twice

I'm writing a C# app (XNA to be specific) and I'm having some very strange behavior when trying to set the window location. The first time I set the location, it places it in a weird place (always the same) but if I set it again, even on the next line, it works.
This is the code I'm using. The initial values in Location are 657, 286. After attempting to set it to 1920, 300, the position becomes 2257, 314. If I run the set again, it correctly updates the position to 1920, 300.
I've tried a full clean and rebuild and tried running in both Debug and Release. I've also tried putting some code before this line just to attempt to rule out a timing issue. I'm totally stumped here, so any help would be greatly appreciated.
var form = (System.Windows.Forms.Form)System.Windows.Forms.Control.FromHandle( this.Window.Handle );
form.Location = new System.Drawing.Point( 1920, 300 );
To set the location of the form try this:
this.Location = new System.Drawing.Point(1920, 300)
Note that this assumes the form you are trying to reposition is the parent object of the method you are calling.

Incorrect screen resolution is retrieved using HtmlPage.Window.Eval("screen.width").ToString()

I have developed a web page using Silverlight. When I tried to retrieve the screen resolution of my PC (which is set to 1366 X 768) using the C# code,
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
string width = HtmlPage.Window.Eval("screen.width").ToString();
string Height = HtmlPage.Window.Eval("screen.height").ToString();
}
it shows the incorrect screen resolution, as 1024 X 768.
What is the reason behind this?
Try like this:
var width = HtmlPage.Window.Eval("screen.availWidth");
var height = HtmlPage.Window.Eval("screen.availHeight");
Since this is not the screen size that you want to know about, and not the window size, you might use SystemParameters.PrimaryScreenWidth and SystemParameters.PrimaryScreenHeight.
You might also find it useful to do some computation with your window's size, the SystemParameters.WindowCaptionHeight, SystemParameters.ResizeFrameHorizontalBorderHeight, and SystemParameters.ResizeFrameVerticalBorderWidth.
All this works fine with standards windows, if you use a 'ToolWindow' WindowStyle, you might need other values.
Note that depending on OS (Windows XP and Windows Vista at least), the figures provided may be 'strange' because they are scaled with a DPI parameter I sometimes found hard to understand (on Windows Vista I develop a program that targets Windows XP, and both do not behave the same). For sure: if you have a wide screen (which is your case), the DPI parameter is automaticly changed on Windows Vista and is not the default 96 DPI. To solve those issues, have a look at PresentationSource, and its member CompositionTarget.
The following code will give you the real coordinates/sizes and not the ones changed by the DPI setting.
var PS = PresentationSource.FromVisual(MyWindow);
var realX = myX* PS.CompositionTarget.TransformToDevice.M11;
var realY = myY* PS.CompositionTarget.TransformToDevice.M22;

System.Drawing.Icon constructor throwing "Operation completed successfully" exception

On a Windows XP machine, the following code is throwing a System.ComponentModel.Win32Exception with the message "The operation completed successfully"
System.Drawing.Icon icon = new System.Drawing.Icon("icon.ico");
I can stop the program crashing with
try
{
System.Drawing.Icon icon = new System.Drawing.Icon("icon.ico");
}
catch(System.ComponentModel.Win32Exception ex)
{
if (ex.NativeErrorCode != 0)
{
throw;
}
}
but of course the icon is not set.
The full stack trace is
at System.Drawing.Icon.Initialize(Int32 width, Int32 height)
at System.Drawing.Icon..ctor(String fileName, Int32 width, Int32 height)
at System.Drawing.Icon..ctor(String fileName)
at hermes.Window1..ctor() in D:\\projects\\hermesclient\\hermesWPF\\hermes\\Window1.xaml.cs:line 50"
That line 50 is the original line I posted.
This is a WPF app, and on a Windows 7 machine the code works fine.
EDIT: Turned out the icon wasn't working in Windows XP at all, adding 256 colour versions seems to have fixed it.
From the looks of it the problem seems to be an issue with not disposing with objects properly. It's hard to pin point exactly where the issue in your case is occurring but as a general rule of thumb make sure you implement the using directive when dealing with objects that implement IDisposable.
Even in the sample you have provided try doing something like:
using (var icon = new System.Drawing.Icon("icon.ico"))
{
// use icon
}
// icon is then disposed.
Have a read of this article.
Does the file icon1.ico exists in the same directory as the .NET executable? You did not say explicitly...are you reading this as an external icon file? perhaps this
string sPath2Icon = Path.Combine(Environment.CurrentDirectory, "icon1.ico");
using (System.Drawing.Icon icon = new System.Drawing.Icon(sPath2Icon)){
// Do what you have to do with icon!
}
Hope this helps,
Best regards,
Tom.
I had a similar problem. in my case the icon file was a multiicon file containing 32x32, 48x48 and 256x256 size icons. I changed it to a single icon file size 32x32 and it worked fine after that.
Turned out the icon wasn't working in Windows XP at all, adding 256 colour versions seems to have fixed it.

Categories

Resources