PowerPoint Viewer Embed issues - c#

I've embedded a PowerPoint Viewer in my main form in order to display a pptx file. I have 2 monitors on my pc and am trying to run the app on my 2nd monitor. When I run the program on monitor 1, everything works as expected. But when I run it on monitor 2 (meaning I change the code to run the app on the 2nd monitor, not run the app and then move it myself to the 2nd monitor), the PowerPoint Viewer opens on the 1st monitor, then moves to the 2nd monitor where the program is running. I believe it has to do with the PowerPoint object not having the parent set properly but not too sure. Here's my code:
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindow(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool SetWindowText(IntPtr hwnd, String lpString);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, UIntPtr lParam);
public const uint WM_SETFOCUS = 0x0007;
Microsoft.Office.Interop.PowerPoint.Application application;
Microsoft.Office.Interop.PowerPoint.Presentation presentation;
public MainForm()
{
InitializeComponent();
DisplayOnMonitor();
}
private void MainForm_Load(object sender, EventArgs e)
{
LoadSlideShow();
}
private void LoadSlideShow()
{
IntPtr screenClasshWnd = (IntPtr)0;
IntPtr x = (IntPtr)0;
application = new Microsoft.Office.Interop.PowerPoint.Application();
presentation = application.Presentations.Open2007(
Settings.Default.PowerPointPath,
Microsoft.Office.Core.MsoTriState.msoTrue,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse,
Microsoft.Office.Core.MsoTriState.msoFalse);
Microsoft.Office.Interop.PowerPoint.SlideShowSettings sst1 = presentation.SlideShowSettings;
sst1.LoopUntilStopped = Microsoft.Office.Core.MsoTriState.msoTrue;
Microsoft.Office.Interop.PowerPoint.SlideShowWindow sw = sst1.Run();
IntPtr pptptr = (IntPtr)sw.HWND;
SetParent(pptptr, splitContainerControl.Panel1.Handle);
splitContainerLeft.Panel1.LostFocus += new EventHandler(OnLostFocus);
splitContainerControl.PreviewKeyDown +=new PreviewKeyDownEventHandler(OnPreviewKeyDown);
splitContainerLeft.Panel1.AutoSize = true;
splitContainerControl.Panel1.Focus();
}
private void DisplayOnMonitor()
{
Screen[] sc;
sc = Screen.AllScreens;
this.FormBorderStyle = FormBorderStyle.None;
this.Left = sc[1].Bounds.Width;
this.Top = sc[1].Bounds.Height;
this.StartPosition = FormStartPosition.Manual;
this.Location = sc[1].Bounds.Location;
Point p = new Point(sc[1].Bounds.Location.X, sc[1].Bounds.Location.Y);
this.Location = p;
this.WindowState = FormWindowState.Maximized;
}
I know the PowerPoint Viewer appears when the sst1.Run() method is called, but I tried to make the app invisible before (and after) that but it throws an exception. If there was a way to instruct sst1 which display to open on, then I think it would resolve the issue, but I haven't had any luck with that so far.
Any help is appreciated!

Related

Autoresize called process within a panel C#

I have the following code that opens notepad within a tabControl panel, this works when I start the form maximized.
this.WindowState = FormWindowState.Maximized
Tab Opening:
TabPage tp = new TabPage("notepad");
Panel tb = new Panel();
tb.Dock = DockStyle.Fill;
tp.Controls.Add(tb);
myTab.TabPages.Add(tp);
The problem is when I launch the form not maximized, opens Notepad then resize the form, the following happens (see picture link) --- notepad doesn't stretch out.
After Opening Notepad within Panel the form is maximized
Any suggestions? Thanks!
[DllImport("user32.dll", SetLastError = true)]
private static extern uint SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("USER32.DLL")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("USER32.DLL")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
private const int GWL_STYLE = (-16);
public static int WS_BORDER = 0x00800000;
public static int WS_CAPTION = WS_BORDER;
public static void loadProcess()
{
Process p = Process.Start("Notepad");
p.WaitForInputIdle();
p.Refresh();
int WS_VISIBLE = GetWindowLong(p.MainWindowHandle, GWL_STYLE);
SetWindowLong(p.MainWindowHandle, GWL_STYLE, (WS_VISIBLE & ~WS_CAPTION));
SetParent(p.MainWindowHandle, panel1.Handle);
ShowWindow(p, SW_SHOWMAXIMIZED);
}
[DllImport("user32.dll")]
private static extern
bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
private const int SW_SHOWMAXIMIZED = 3;
private static bool ShowWindow(Process _Process, int nCmdShow)
{
return ShowWindowAsync(_Process.MainWindowHandle, nCmdShow);
}
After few trials, I was able to resize it automatically.
On my loadProcess method, I have stored the process in a hashtable for reference later.
Process p = Process.Start("Notepad");
p.WaitForInputIdle();
sessions.Add(tabName, p);
on tabControl1_Selecting event:
String name = myProcess.SelectedTab.Name;
Process pHandle = (Process) sessions[name];
SetForegroundWindow(pHandle.MainWindowHandle);
SetFocus(pHandle.MainWindowHandle);
MoveWindow(pHandle.MainWindowHandle, 0, 0, this.Width, this.Height, true);
I've added a Form1_Resize event so it will resize accordingly.
String name = myProcess.SelectedTab.Name;
Process pHandle = (Process) sessions[name];
MoveWindow(pHandle.MainWindowHandle, 0, 0, this.Width, this.Height, true);

Outlook security prompt auto approval

I'm writing a function that will allow users to import their e-mails from outlook in to corporate storage. But I've encounter a problem with security promt, and since we still have clients with office 2003 we can't disable it.
I'm trying to autoclick it with this code:
[DllImport("User32.dll")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, int msg, int wParam, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, string windowTitle);
private const int WM_LBUTTONDOWN = 0x201;
private const int WM_LBUTTONUP = 0x0202;
private void button1_Click(object sender, EventArgs e)
{
int hwnd = 0;
IntPtr hwndChild = IntPtr.Zero;
while (true)
{
hwnd = FindWindow(null, "Microsoft Outlook");
if (hwnd != 0)
{
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "Button", "Yes");
if (hwndChild != IntPtr.Zero)
{
SendMessage((int)hwndChild, WM_LBUTTONDOWN, 0, IntPtr.Zero);
SendMessage((int)hwndChild, WM_LBUTTONUP, 0, IntPtr.Zero);
}
else
{
//...
}
}
else
{
//...
}
hwnd = 0;
}
}
But when I'm trying to use that code I've encounter unexpected problem. Security promt will only disappear only when I'm actually performing mouse click no matter where even on some empty screen space. What is wrong with it?
Try out MAPILab's Advanced Security for Outlook. Should also work for Outlook 2003. This will let you give a permanent access for your application - a pop-up window will show only the first time you access Outlook items:
http://www.mapilab.com/outlook/security/
Advanced Security will have to be installed on each machine you run your app. It's free for noncommercial and commercial use.
You should try using SendKeys and send Y for Yes.

Switch to last active application like Alt-Tab

ok, I have found many posts on finding a window by name, etc. What I have not found is how to find and switch the window application focus to last active window. The code I am showing below will give me the list of active applications in the task manager that are active.
What I can not figure out how to do is figure out what application was the last active application, and then switch to it. for example...
I have my custom winform application open.
I click a button
My application switches to the last active window / application.
Here is the working code I have so far. (this is the action on a button, and it expects that the application has a textbox named textbox1. you will also need to add using System.Diagnostics;
private void button1_Click(object sender, EventArgs e)
{
Process[] procs = Process.GetProcesses();
IntPtr hWnd;
foreach (Process proc in procs)
{
if ((hWnd = proc.MainWindowHandle) != IntPtr.Zero)
{
textBox1.Text += (proc.ProcessName.ToString());
textBox1.Text += "\t";
textBox1.Text += (hWnd.ToString());
textBox1.Text += "\r\n";
}
}
}
Check this article out: http://www.whitebyte.info/programming/how-to-get-main-window-handle-of-the-last-active-window
Specifically, this code:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[...]
IntPtr targetHwnd = GetWindow(Process.GetCurrentProcess().MainWindowHandle, (uint)GetWindow_Cmd.GW_HWNDNEXT);
while (true)
{
IntPtr temp = GetParent(targetHwnd);
if (temp.Equals(IntPtr.Zero)) break;
targetHwnd = temp;
}
SetForegroundWindow(targetHwnd);
Since my comments didn't help you, here's a little resume (didn't test it though):
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
static extern IntPtr GetLastActivePopup(IntPtr hWnd);
[DllImport("user32.dll", ExactSpelling = true)]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
const uint GA_PARENT = 1;
const uint GA_ROOT = 2;
const uint GA_ROOTOWNER = 3;
public IntPtr GetPreviousWindow()
{
IntPtr activeAppWindow = GetForegroundWindow();
if ( activeAppWindow == IntPtr.Zero )
return IntPtr.Zero;
IntPtr prevAppWindow = GetLastActivePopup(activeAppWindow);
return IsWindowVisible(prevAppWindow) ? prevAppWindow : IntPtr.Zero;
}
public void FocusToPreviousWindow()
{
IntPtr prevWindow = GetPreviousWindow();
if ( prevWindow != IntPtr.Zero )
SetForegroundWindow(prevWindow);
}

How to get ScrollBar positions of Notepad inside my form

I have a problem with getting scrollbar positions. Is it possible to get the scrollbar position of another process for example Notepad. I wrote small app where i tested and always get 0 0 as a position of scrollbars.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll")]
static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
private void Form1_Load(object sender, EventArgs e)
{
this.SuspendLayout();
Process notepad = new Process();
ProcessStartInfo psi = new ProcessStartInfo(#"c:\list1.txt");
psi.WindowStyle = ProcessWindowStyle.Normal;
notepad.StartInfo = psi;
notepad.Start();
this.ResumeLayout();
notepad.WaitForInputIdle(3000);
IntPtr old = SetParent(notepad.MainWindowHandle, this.Handle);
SetWindowLong(notepad.MainWindowHandle, GWL_STYLE, WS_VISIBLE + WS_MAXIMIZE);
MoveWindow(notepad.MainWindowHandle, 100, 100, 400, 400, true);
SetActiveWindow(notepad.MainWindowHandle);
SwitchToThisWindow(notepad.MainWindowHandle, true);
}
I have button which send PGDN event to notepad and it works great but after pgdn event position of scrollbar also is 0 0
private void PGDN_Click(object sender, EventArgs e)
{
Process[] procs = Process.GetProcessesByName("Notepad");
IntPtr hwnd = procs[0].MainWindowHandle;
SetActiveWindow(hwnd);
SwitchToThisWindow(hwnd, true);
Thread.Sleep(2000);
SendKeys.SendWait("{PGDN}");
Thread.Sleep(2000);
label1.Text = "OK";
label1.Text = "";
label1.Text = HScrollPos().ToString() + " " + VScrollPos().ToString(); }
Here are the HScrollPos and VScrollPos functions :
public int VScrollPos()
{
Process[] procs = Process.GetProcessesByName("Notepad");
IntPtr hwnd = procs[0].MainWindowHandle;
if (procs.Length != 0)
{
return GetScrollPos(hwnd , SB_VERT);
}
else
{
MessageBox.Show("Notepad Nor Running");
return 0;
}
}
public int HScrollPos()
{
Process[] procs = Process.GetProcessesByName("Notepad");
IntPtr hwnd = procs[0].MainWindowHandle;
if (procs.Length != 0)
{
return GetScrollPos(hwnd , SB_HORZ);
}
else
{
MessageBox.Show("Notepad Nor Running");
return 0;
}
}
Maybe there is another way to get Scrollbar Position of another process/window in windows? Please Help. Thx for granted.
And here is the Working Code based on Answer. Thx
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
private void button4_Click(object sender, EventArgs e)
{
string lpszParentClass = "Notepad";
string lpszParentWindow = "Untitled - Notepad";
string lpszClass = "Edit";
IntPtr ParenthWnd = new IntPtr(0);
IntPtr hWnd = new IntPtr(0);
ParenthWnd = FindWindow(lpszParentClass, lpszParentWindow);
if (ParenthWnd.Equals(IntPtr.Zero))
MessageBox.Show("Notepad Not Running");
else
{
hWnd = FindWindowEx(ParenthWnd, hWnd, lpszClass, "");
if (hWnd.Equals(IntPtr.Zero))
MessageBox.Show("Notepad doesn't have an edit component ?");
else
{
MessageBox.Show("Notepad Window: " + ParenthWnd.ToString());
MessageBox.Show("Edit Control: " + hWnd.ToString());
}
}
SetActiveWindow(ParenthWnd);
label5.Text = GetScrollPos(hWnd, SB_VERT) + " " + GetScrollPos(hWnd, SB_HORZ);
}
I suspect the problem is that you are using the main window handle, you should be using the handle of the Edit control, which is a child of the main window.
Using the main window hwnd you can enumrate the child windows to find the hWnd of the edit control and then use that hWnd in your call to get the scroll bar position.
SendKeys is working because it is sending the key stroke to the window that has input focus which in this case is the Edit control.
Here is an answer to a question I provided sometime back that will help with the interop for EnumChildWindows if you need, there is a lot more there but it might help.

How do I get the title of the current active window using c#?

I'd like to know how to grab the Window title of the current active window (i.e. the one that has focus) using C#.
See example on how you can do this with full source code here:
http://www.csharphelp.com/2006/08/get-current-window-handle-and-caption-with-windows-api-in-c/
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
private string GetActiveWindowTitle()
{
const int nChars = 256;
StringBuilder Buff = new StringBuilder(nChars);
IntPtr handle = GetForegroundWindow();
if (GetWindowText(handle, Buff, nChars) > 0)
{
return Buff.ToString();
}
return null;
}
Edited with #Doug McClean comments for better correctness.
If you were talking about WPF then use:
Application.Current.Windows.OfType<Window>().SingleOrDefault(w => w.IsActive);
Based on GetForegroundWindow function | Microsoft Docs:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int GetWindowTextLength(IntPtr hWnd);
private string GetCaptionOfActiveWindow()
{
var strTitle = string.Empty;
var handle = GetForegroundWindow();
// Obtain the length of the text
var intLength = GetWindowTextLength(handle) + 1;
var stringBuilder = new StringBuilder(intLength);
if (GetWindowText(handle, stringBuilder, intLength) > 0)
{
strTitle = stringBuilder.ToString();
}
return strTitle;
}
It supports UTF8 characters.
Loop over Application.Current.Windows[] and find the one with IsActive == true.
Use the Windows API. Call GetForegroundWindow().
GetForegroundWindow() will give you a handle (named hWnd) to the active window.
Documentation: GetForegroundWindow function | Microsoft Docs
If it happens that you need the Current Active Form from your MDI application: (MDI- Multi Document Interface).
Form activForm;
activForm = Form.ActiveForm.ActiveMdiChild;
you can use process class it's very easy.
use this namespace
using System.Diagnostics;
if you want to make a button to get active window.
private void button1_Click(object sender, EventArgs e)
{
Process currentp = Process.GetCurrentProcess();
TextBox1.Text = currentp.MainWindowTitle; //this textbox will be filled with active window.
}

Categories