changing screen orientation programmatically in mirror mode windows 7 - c#

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.

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.

Problems with PrimaryScreen.Size

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.

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;

Managed DirectX9 ColorKey

I've managed to load a texture with TextureLoader.LoadFromFile(), and provided it with Color.Black.ToArgb() for it's colorkey.
Unfortunately, when I render it, using Device.DrawUserPrimitives, I'm still seeing black.
Am I missing some code to enable the use of the ColorKey?
Needed to set some renderstate on the Device:
Device.RenderState.AlphaBlendEnable = true;
Device.RenderState.SourceBlend = Blend.SourceAlpha;
Device.RenderState.DestinationBlend = Blend.InvSourceAlpha;
I'm not certain which but I think you need to enable the render state(s) AlphaBlendEnable and/or AlphaTestEnable. You might also have to set the blend modes.
By the way, you're using Managed DirectX, which has long been discontinued. You should consider switching to XNA or SlimDX.

Textures not working in opengl/Tao for C# on intel chipsets

I've got a lot of OpenGl rendering code in a C# .NET 3.5 sp1 application. Some of the code can be found in this question.
Huge problem: The code is not running at all on intel chipsets, such as the 915M or the Q35. These chipsets are spec'd to run opengl 1.4, and my code is all power-of-two nice and so forth. I've tried updating to the latest drivers from either Dell or Intel, depending on the machine.
There are two types of crash failures:
Failing on glActiveTextureARB. 915M apparently does not include that in its extensions.
Failing on shader loading, namely glGenProgramsARB.
Trying to call these functions on the 915M in XP or the Q35 on Windows 7 causes either a freeze or a crash, depending on what the machine is feeling like at the moment.
There's another worse failure, and that's that the display is not fixing that previous question, ie, the rendered display looks like it's showing 8 bit data when it should be showing 16. That's happening on the Q35 chipset, latest dell drivers, running XP.
Any thoughts on this? I'm considering going back to glDrawPixels, because even while that's slow, it works.
EDIT: more code! The following code fails with an GL_INVALID_VALUE error on both a windows xp a windows 7 machine with the Q35 chipset:
const int mSize = 256;
ushort[] theImage = new ushort[mSize * mSize];
...
//datasetup
int x, y, i = 0 ;
for (x = 0; x < mSize; x++) {
for (y = 0; y < mSize; y++) {
theImage[(y * mSize) + x] = (ushort)i++;
}
}
...
//onpaint
int theTexName;
Gl.glGenTextures(1, out theTexName);
Gl.glBindTexture(Gl.GL_TEXTURE_2D, theTexName);
Gl.glTexImage2D(Gl.GL_TEXTURE_2D, 0, Gl.GL_LUMINANCE16, mSize, mSize,
0, Gl.GL_LUMINANCE, Gl.GL_UNSIGNED_SHORT, theImage);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MIN_FILTER, Gl.GL_LINEAR);
Gl.glTexParameteri(Gl.GL_TEXTURE_2D, Gl.GL_TEXTURE_MAG_FILTER, Gl.GL_LINEAR);
//theMagBuffer = null;
Gl.glDisable(Gl.GL_BLEND);
Gl.glEnable(Gl.GL_TEXTURE_2D);
Gl.glPolygonMode(Gl.GL_FRONT_AND_BACK, Gl.GL_FILL);
Gl.glColor4d(1.0, 1.0, 1.0, 1.0);
Gl.glPushMatrix();
Gl.glBindTexture(Gl.GL_TEXTURE_2D, theTexName);
Gl.glBegin(Gl.GL_QUADS);
Gl.glTexCoord2f(0, 1);
Gl.glVertex2f(0, mSize);
Gl.glTexCoord2f(0, 0);
Gl.glVertex2f(0, 0);
Gl.glTexCoord2f(1, 0);
Gl.glVertex2f(mSize, 0);
Gl.glTexCoord2f(1, 1);
Gl.glVertex2f(mSize, mSize);
Gl.glEnd();
Gl.glDisable(Gl.GL_TEXTURE_2D);
Gl.glDisable(Gl.GL_FRAGMENT_PROGRAM_ARB);
Gl.glPopMatrix();
GetGLError("MAG");
Gl.glFinish();
Cheers,
sadly, you cannot do anything about the crashes, it seems like the extensions in question are not supported on those chipsets. Your app is not compatible with them, end of story. Just to make sure, use glGetString(GL_EXTENSIONS) to see what extensions are there. You can even do that in your application on startup and display a nice message box telling the user that some extensions that are required to run are not supported by the hardware, instead of just crashing.
As for the 8bit / 16bit question, using LUMINANCE16 doesn't really guarantee that 16 bit texture will be used, many drivers "emulate" this format using 8 bit textures without telling you. This is used to improve compatibility, as annoying as it is.
If you want true 16 bit, use 8 bit LUIMNANCE_ALPHA which should be suported pretty much anywhere and pack the two 8 bit components to a single number inside shader.

Categories

Resources