I have seen numerous posts on this subject here, but none seem to answer this issue directly. I want to control two instances of Powerpoint running on a second monitor.
The ideal solution looks like this:
PowerPoint.Application PPTViewer1 = new PowerPoint.Application();
PowerPoint.Application PPTViewer2 = new PowerPoint.Application();
I can do this manually, simply by starting two instances of PowerPoint, loading the presentation, and starting the slide show from each instance. I can toggle back and forth between the two slide shows manually, with each being brought to the front as expected.
So... how do I do this programatically using VSTO and C#?? Like others before me, I see that the Interop.PowerPoint interface will create only the single instance. If that were not the case, then I could achieve the results I am looking for easily enough.
Additionally, I am not looking for a third party component for this task.
Any help is appreciated.
Thanks in advance.
It may appear that you're running multiple instances of Powerpoint, but you're not. It only allows one instance of itself. If you see two instances of Powerpnt.exe in the task list, as sometimes happens, it means that something's gone wrong and left a zombie in memory.
May not be totally ideal but here is a reference that suggested to start an instance as a different user (Note that this site is for PowerPoint 2007).
runas /user:username "C:\Program Files\Microsoft Office\Office12\POWER PNT.EXE"
Each instance of the Powerpoint COM object shares the same fullscreen display window. I know of no method to switch which presentation has that window
The solution is to host the Powerpoint display in your own window
This therefore allows you to scale the window and show multiple presentations on one monitor, or move it from one monitor to another?
e.g.
var display1 = new FullScreenDisplay(); // A form with BorderStyle = None
display1.Show();
application1 = new PowerPoint.Application();
presentation1 = application1.Presentations.Open2007(....);
var slideShowSettings1 = presentation1.SlideShowSettings;
slideShowSettings1.ShowType = PowerPoint.PpSlideShowType.ppShowTypeSpeaker;
var slideShowWindow1 = slideShowSettings1.Run();
IntPtr hwnd1 = (IntPtr)slideShowWindow1.HWND;
SetParent(hwnd1, display1.Handle);
var display2 = new FullScreenDisplay();
display2.Show();
application2 = new PowerPoint.Application();
presentation2 = application2.Presentations.Open2007(....);
var slideShowSettings2 = presentation2.SlideShowSettings;
slideShowSettings2.ShowType = PowerPoint.PpSlideShowType.ppShowTypeSpeaker;
var slideShowWindow2 = slideShowSettings2.Run();
IntPtr hwnd2 = (IntPtr)slideShowWindow2.HWND;
SetParent(hwnd2, display2.Handle);
display1.BringToFront(); // to show slideshow 1
// or
display2.BringToFront(); // to show slideshow 2
// To advance a slide
presentation1.SlideShowWindow.View.Next();
// or
presentation2.SlideShowWindow.View.Next();
// To exit, note order!
presentation2.SlideShowWindow.View.Exit();
presentation1.SlideShowWindow.View.Exit();
Application.Exit();
This is a hack, and may not work in future versions of Powerpoint?
You also need this import
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
Related
I'm currently creating a WPF application, and like to add as a small side feature the ability to clear the windows file explorer history.
If one were to manually do this operation, it is possible via the file menu within a file explorer window,
as shown here.
My goal is pretty much to programmatically execute the same action as this button does, but I've been unable to find what executable or user32.dll method is behind this operation (if it exists), and been also unsuccessful on finding the full logic behind it (namely, finding what folder and files it targets), to replicate it.
Can you help me?
As the comment by dxiv suggested, you can achieve this via the following:
enum ShellAddToRecentDocsFlags
{
Pidl = 0x001,
Path = 0x002,
PathW = 0x003
}
[DllImport("shell32.dll", CharSet = CharSet.Unicode)]
private static extern void SHAddToRecentDocs(ShellAddToRecentDocsFlags flag, string path);
// How To Clear Everything
SHAddToRecentDocs(ShellAddToRecentDocsFlags.Pidl, null);
I am trying to create an application in C# using which I need to change the BackColor/Forecolor of some specific controls in another process/application. For example I have few application running in my machine. When I run the new C# application (which does not have any UI), the backcolor/forecolor of few controls in other applications should be changed to the new colors which I set. And when I close the application, the colors should be reset to the original colors. I tried the SetTextColor, SetBkColor windows apis from gdi32 but they dont work. Could you suggest me how can I achieve this?
Note: The coordinates of the controls for which the colors need to be changed are already noted and I am using the WindowFromPoint api to get the handle of the control.
This is the code which I tried.
point = new Point(1340, 144);
IntPtr hWnd = DllImports.WindowFromPoint(point);//this is a button control in one of the applications
if (hWnd != IntPtr.Zero)
{
IntPtr wDC = DllImports.GetDC(hWnd);
int result = DllImports.SetBkMode(wDC, TRANSPARENT);
int i = DllImports.SetTextColor(wDC, ColorTranslator.ToWin32(Color.Red));
i = DllImports.SetBkColor(wDC, ColorTranslator.ToWin32(Color.Yellow));
result = DllImports.SetBkMode(wDC, OPAQUE);
}
Thanks in advance
I am using the DataTransferManager in my Win32 Desktop Bridge App to share text and links.
I am using the samplecode from
Microsofts Code examples (github)
However the share dialog is empty (see image, its says "Try again, Could not show all available methods to share").
Loading DataTransferManagerHelper
IntPtr hwnd = new WindowInteropHelper(Application.Current.MainWindow).Handle;
var dtm = DataTransferManagerHelper.GetForWindow(hwnd);
dtm.DataRequested += OnDataRequested;
Showing Share UI
IntPtr hwnd = new WindowInteropHelper(Application.Current.MainWindow).Handle;
DataTransferManagerHelper.ShowShareUIForWindow(hwnd);
I was able to find the bug.
I was not actually calling the methods
DataTransferManagerHelper.GetForWindow(hwnd);
dtm.DataRequested += OnDataRequested;
Makes sure that these two methods get called otherwise you will get the "no content" share dialog.
Hi
Could some one help me for this problem:
How to activate a presentation window by using its name?
foreach (PPT.Presentation ppt in ppApp.Presentations)
{
if (ppt.Name == strTargetFileName)
{
//Then activate this ppt. How to do this?
}
You can launch a PowerPoint with Process.Start:
Process.Start(#"c:\users\foo\Documents\Bar.ppt");
If you need to actually launch it in slideshow mode, you can do:
Process.Start("powerpnt", "/s \"C:\\Users\\Foo\\Documents\\Bar.ppt\"");
You should find window handle first with FindWindow function and when activate it with SetForegroundWindow function. Check this page, sample code there performs actually what you are looking for
first add a reference ( rigth click solution explorer to Microsoft PowerPoint XX Object)
using MSPPOINT = Microsoft.Office.Interop.PowerPoint;
define a instance of the object
MSPPOINT._Application pwpApp = new MSPPOINT.Application();
MSPPOINT._Presentation pwpDoc = null;
pwpApp.Activate();
pwpDoc = pwpApp.Presentations.Open(#"D:\Temp\Document.pptx", Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoFalse);
//enter code here
and do something with him..
Good Luck !
Is it possible to enable a second monitor programatically and extend the Windows Desktop onto it in C#? It needs to do the equivalent of turning on the checkbox in the image below.
MSDN Device Context Functions
What you basically need to do:
Use the EnumDisplayDevices() API call
to enumerate the display devices on
the system and look for those that
don't have the
DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
flag set (this will include any
mirroring devices so not all will be
physical displays.) Once you've found
the display device you'll need to get
a valid display mode to change it to,
you can find this by calling the
EnumDisplaySettingsEx() API call -
Generally you'd display all the
available modes and allow the user to
choose however in your case it sounds
like this may be possible to hard-code
and save you an additional step. For
the sake of future-proofing your
application though I'd suggest having
this easily changeable without having
to dig through the source every time,
a registry key would be the obvious
choice. Once you've got that sorted
out populate a DevMode display
structure with the information about
the display positioning (set the
PelsWidth/Height, Position,
DisplayFrequency and BitsPerPel
properties) then set these flags in
the fields member. Finally call
ChangeDisplaySettingsEx() with this
settings structure and be sure to send
the reset and update registry flags.
That should be all you need, hope this
helps,
DISPLAY_DEVICE structure import using PInvoke
EnumDisplayDevices function import
EnumDisplaySettingsEx function import
etc. the rest of them functions can be found with a simple search by name.
If you have windows 7, then just start a process:
private static Process DisplayChanger = new Process
{
StartInfo =
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden,
FileName = "DisplaySwitch.exe",
Arguments = "/extend"
}
};
then DisplayChanger.Start();
I don't have the full answer here but I am almost sure that you will have to call out of .Net to do this. You will have to use Pinvoke to call an unmanaged dll. A great resource for this is pinvoke.net.
I did a quick search and found http://www.pinvoke.net/default.aspx/user32/ChangeDisplaySettings.html which probably isn't exactly what you want but you will probably find it somewhere on pinvoke.net
I am looking for the same solution. I have written the following code to call ChangeDisplaySettingsEx with PInvoke:
DEVMODE dm = new DEVMODE();
dm.dmSize = (short)Marshal.SizeOf(dm);
dm.dmPelsWidth = 1680;
dm.dmPelsHeight = 1050;
dm.dmBitsPerPel = 32;
dm.dmDisplayFrequency = 60;
dm.dmFields = DevModeFields.DM_BITSPERPEL | DevModeFields.DM_PELSWIDTH |
DevModeFields.DM_PELSHEIGHT | DevModeFields.DM_DISPLAYFREQUENCY;
int res = ChangeDisplaySettingsEx(#"\\.\DISPLAY2", ref dm, IntPtr.Zero, CDS_RESET | CDS_UPDATEREGISTRY, IntPtr.Zero);
Console.WriteLine("result = " + res.ToString());
If the monitor is already enabled, this changes the resolution successfully. But if the monitor isn't attached to the desktop already, this won't activate it. So does anyone have a code example that works?
To enable a monitor, set its position to something other than 0,0, like as shown:
POINTL enabledPosition = new POINTL();
enabledPosition.x = -1280;
enabledPosition.y = 0;
dm.dmPosition = enabledPosition;
dm.dmFields = DM.Position;
res = ChangeDisplaySettingsEx(d.DeviceName, ref dm, IntPtr.Zero, (uint) DeviceFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);