Copy main menu from one window to other - c#

I am trying to set a new parent window (host window) for the another window (client window) that belongs to other process. Also, the is a requirement to duplicate main menu of the client window so that the host window should have the same working main menu as the calient window has.
I managed to set the client window menu to the host window, but the host menu does not work. It is possible to navigate through menu, but is does not work (f.e. it not possible to open/create new file).
The question is if it possible to do this at all and if it is, what did I miss?
There is a code snippet:
public partial class Form1 : Form
{
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
private static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool SetMenu(IntPtr hWnd, IntPtr hMenu);
private Process notepadProcess;
public Form1()
{
InitializeComponent();
}
private void Form1_Shown(object sender, EventArgs e)
{
ProcessStart();
Thread.Sleep(100);
EmbedNotepadWindow();
}
private void ProcessStart()
{
notepadProcess = new Process();
notepadProcess.StartInfo.FileName = "notepad.exe";
notepadProcess.Start();
}
private void EmbedNotepadWindow()
{
SetParent(notepadProcess.MainWindowHandle, panel1.Handle);
var menuHandle = GetMenu(notepadProcess.MainWindowHandle);
SetMenu(this.Handle, menuHandle);
}
}
Copy main menu from Client to Host window

Related

Black WPF Window when activating it from another application?

i am developing a wpf app, but i have a problem
when i activate my app from another application it shows totally black(demo on the bottom)
this code of activating my window work great but the window shows black
class WinApi2
{
public const int SW_SHOWNORMAL = 5;
[DllImportAttribute("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImportAttribute("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImportAttribute("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
public static void ShowToFront(string windowName)
{
IntPtr firstInstance = FindWindow(null, windowName);
ShowWindow(firstInstance, SW_SHOWNORMAL);
SetForegroundWindow(firstInstance);
}
}
// Activating my window by calling:
ShowToFront(".");
The result :
i found a solution by calling This.Show(); on the Activated Event of my wpf window
public void Window_Activated(object sender, EventArgs e)
{
this.Show();
}
but when doing that the black window still there it shows for a quick time and goes like flash that give a bad locking at the app showing.
i tried the same code to show another app(created with c plus plus) no problem, but the problem is just with wpf apps i think Winforms too ! who can i solver this problem ??

Activate Window and Send Input using SetForegroundWindow and SendKeys in C#

What I'm trying to do is activate another application and send a key input to it to trigger a button. However this code doesn't seem to work. It looks like it can find the application but it does not activate it, and does not send the key.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private void debugButton_Click(object sender, EventArgs e)
{
//GetProcess by Class
IntPtr rightNowHandle = FindWindow("WindowsForms10.Window.8.app.0.24dc298_r17_ad2", null);
//Get Handle by Process
Process proc = Process.GetProcessesByName("RightNow.CX")[0];
IntPtr ptrFF = proc.MainWindowHandle;
//Get a handle for the Calculator Application main window
if (rightNowHandle == IntPtr.Zero)
{
MessageBox.Show("Could Not Find Right Now");
return;
}
SetForegroundWindow(rightNowHandle); //Activate Handle By Class
//SetForegroundWindow(ptrFF); //Activate Handle By Process
SendKeys.SendWait("{F1}");
}
And here is what I pull with Window Spy
Any help would be greatly appreciated. Thanks.
Figured out my issue.
SetForegroundWindow does not show the application if it's minimized, which is what I was anticipating.
Next I used Windows Input Simulator, to send the input instead of SendKeys.
Here's the code I ended up using.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
private const int SW_RESTORE = 9;
private void debugButton_Click(object sender, EventArgs e)
{
//GetProcess by Class
IntPtr rightNowHandle = FindWindow("WindowsForms10.Window.8.app.0.24dc298_r17_ad2", null);
//Get Handle by Process
Process proc = Process.GetProcessesByName("RightNow.CX")[0];
IntPtr ptrFF = proc.MainWindowHandle;
//Get a handle for the Calculator Application main window
if (rightNowHandle == IntPtr.Zero)
{
MessageBox.Show("Could Not Find Right Now");
return;
}
SetForegroundWindow(ptrFF); //Activate Handle By Process
ShowWindow(ptrFF, SW_RESTORE); //Maximizes Window in case it was minimized.
//SetForegroundWindow(rightNowHandle); //Activate Handle By Class
InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.LMENU, VirtualKeyCode.VK_A); //Send Left Alt + A
}

Minimize a folder

I want to minimize a window using C#
Ex : I have opened this path E:\ using
process.start(E:\)
And I want to minimize this path on a certain event.
How can I make that possible?
The following sample Console Application code will minimize all shell explorer views that are opened on E:\ :
class Program
{
static void Main(string[] args)
{
// add a reference to "Microsoft Shell Controls and Automation" COM component
// also add a 'using Shell32;'
Shell shell = new Shell();
dynamic windows = shell.Windows(); // this is a ShellWindows object
foreach (dynamic window in windows)
{
// window is an WebBrowser object
Uri uri = new Uri((string)window.LocationURL);
if (uri.LocalPath == #"E:\")
{
IntPtr hwnd = (IntPtr)window.HWND; // WebBrowser is also an IWebBrowser2 object
MinimizeWindow(hwnd);
}
}
}
static void MinimizeWindow(IntPtr handle)
{
const int SW_MINIMIZE = 6;
ShowWindow(handle, SW_MINIMIZE);
}
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
It's using the Shell Objects for Scripting. Note the usage of the dynamic keyword that's mandatory here because there is no cool typelib, and therefore no intellisense either.
Shell32.Shell objShell = new Shell32.Shell();
objShell.MinimizeAll();
this will help you to minimize all the window Not only Folders all(something like windows + M!!!
Your question is not very clear. If you are using a TreeView control see
MSDN Treeview class. You can then: Expand or Collapse items at will.
You can use the configuration file or a Variable
This is a possible solution and only minimizes the window u opened:
private int explorerWindowNumber;
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MINIMIZE = 0xF020;
[DllImport("user32.dll", SetLastError = true)]
public static extern int GetForegroundWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
public void button1_Click(object sender, EventArgs e)
{
//Start my window
StartMyExplorer();
}
private void StartMyExplorer()
{
Process.Start("D:\\");
Thread.Sleep(1000);
//Get the window id (int)
explorerWindowNumber = GetForegroundWindow();
}
private void button2_Click(object sender, EventArgs e)
{
//Minimize the window i created
SendMessage(explorerWindowNumber, WM_SYSCOMMAND, SC_MINIMIZE, 0);
}

Is it possible to remove resizing and closing of another application with C#?

I was wondering if it is possible to remove the ability to close OTHER windows using C#?
I know that you can override your windows' close() method, but is that also possible for other processes? And what about changing the window style of another process to fixed___ so it cannot be resized?
So far I have gotten the main window handle of the application and I have removed all buttons and menus, but I still need to figure out how to make it uncloseable and unresizeable.
Here's what I've got:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ThirdTest
{
class Program
{
#region Constants
//Finds a window by class name
[DllImport("USER32.DLL")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//Sets a window to be a child window of another window
[DllImport("USER32.DLL")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
//Sets window attributes
[DllImport("USER32.DLL")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
//Gets window attributes
[DllImport("USER32.DLL")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);
[DllImport("user32.dll")]
static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
static extern int GetMenuItemCount(IntPtr hMenu);
[DllImport("user32.dll")]
static extern bool DrawMenuBar(IntPtr hWnd);
[DllImport("user32.dll")]
static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, uint uFlags);
//assorted constants needed
public static uint MF_BYPOSITION = 0x400;
public static uint MF_REMOVE = 0x1000;
public static int GWL_STYLE = -16;
public static int WS_CHILD = 0x40000000; //child window
public static int WS_BORDER = 0x00800000; //window with border
public static int WS_DLGFRAME = 0x00400000; //window with double border but no title
public static int WS_CAPTION = WS_BORDER | WS_DLGFRAME; //window with a title bar
public static int WS_SYSMENU = 0x00080000; //window menu
#endregion
public static void WindowsReStyle()
{
Process[] Procs = Process.GetProcesses();
foreach (Process proc in Procs)
{
Console.WriteLine("Found process: " + proc.ProcessName.ToString());
if (proc.ProcessName.StartsWith("notepad"))
{
IntPtr pFoundWindow = proc.MainWindowHandle;
int style = GetWindowLong(pFoundWindow, GWL_STYLE);
//get menu
IntPtr HMENU = GetMenu(proc.MainWindowHandle);
//get item count
int count = GetMenuItemCount(HMENU);
//loop & remove
for (int i = 0; i < count; i++)
RemoveMenu(HMENU, 0, (MF_BYPOSITION | MF_REMOVE));
//force a redraw
DrawMenuBar(proc.MainWindowHandle);
SetWindowLong(pFoundWindow, GWL_STYLE, (style & ~WS_SYSMENU));
SetWindowLong(pFoundWindow, GWL_STYLE, (style & ~WS_CAPTION));
}
}
}
static void Main(string[] args)
{
WindowsReStyle();
}
}
}
Any ideas? (:
As I've put in the comments, here are some more details on the issue:
I need two applications to be side-by-side on the monitor.
None of them can be closeable or resizeable. One is a browser, the other is an application called "Z-tree".
I have already fixed the issue with Z-tree as it, by default, runs with no closebutton and no resizing and you can specify the size and position of it in the command line.
Here's another idea, create a winforms project and set the window so it cannot be resized. Then embed a single WebBrowser control in the form and navigate to your page in the form load:
private void Form1_Load(object sender, EventArgs e)
{
//catch form closing event to prevent form being closed using alt-f4
FormClosing += Form1_FormClosing;
//remove close button from toolbar and remove window border to prevent
//moving and resizing
this.ControlBox = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
//set position to half of the screen
this.Left = Screen.PrimaryScreen.Bounds.Width / 2;
this.Top = 0;
this.Width = Screen.PrimaryScreen.Bounds.Width / 2;
this.Height = Screen.PrimaryScreen.Bounds.Height;
//mark the window as a top level window, reducing users ability to alt-tab away
TopMost = true;
webBrowser1.Navigate("www.google.com");
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
//prevent form being closed
e.Cancel = true;
}
//the only way to close the form
void DoExit()
{
//remove the closing handler first or it won't close
FormClosing -= Form1_FormClosing;
Close();
}
you can force internet explorer into an "unexitable" fullscreen mode if you start it with:
iexplore -k www.google.com
This is how shops and stuff get it to run so no-one can close it. Of course you can close it through task manager, but it just makes it difficult for most users to close it.
(CTRL-W will close it <--- secret key!)
http://support.microsoft.com/kb/154780

Running only one instance of an application,(Quit new instance and Display old instance or give Focus)

My app has a default setting that makes it run on the Icon tray when you boot your computer.
If you click on the Icon from the Icon tray then the app is displayed on the desktop window.
Further more if a user try to launch a new instance of my app whilst the old one is running, I just display a message that another instance is running and then Quit the new instance.
Now I want the New instance not only to quit but also makes the Old instance active/displayed on the desktop.
This is my present code
if (System.Diagnostics.Process.GetProcessesByName(
System.Diagnostics.Process.GetCurrentProcess().ProcessName).Length > 1)
{
MessageBox.Show(kingCobra.Properties.Resources.Msg_Multiple_Starts,
kingCobra.Properties.Resources.Multiple_Starts,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
System.Diagnostics.Process.GetCurrentProcess().Kill();
return;
}
What you need to do is to add this to your main class:
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
Then you need to obtain a reference to the process that is already running, and then call the SetForegroundWindow method like this:
SetForegroundWindow(SameProcess.MainWindowHandle);
You do not need to kill the current process like you are currently doing, just return after focusing the other process' main window as shown above
This is a full working example:
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
var currentProcess = Process.GetCurrentProcess();
foreach (Process p in Process.GetProcessesByName(currentProcess.ProcessName))
{
if (p.Id != currentProcess.Id)
{
MessageBox.Show("Already running");
SetForegroundWindow(p.MainWindowHandle);
return;
}
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
This is the best way I've ever seen to get this job done.
public class SingleInstanceController : WindowsFormsApplicationBase
{
public SingleInstanceController()
{
IsSingleInstance = true;
}
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
Form1 form = MainForm as Form1;
form.Text = "I will run only once!";
form.Activate();
base.OnStartupNextInstance(eventArgs);
}
protected override void OnCreateMainForm()
{
MainForm = new Form1();
}
}
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
string[] args = Environment.GetCommandLineArgs();
SingleInstanceController controller = new SingleInstanceController();
controller.Run(args);
}
}
Actual code from this article Single Instance Application.
Note: this requires you to add reference of Microsoft.VisualBasic.dll
I finally Got what I wanted from Here. My main problem was to bring the old instance from the Icon tray whilst closing the new
static class Program
{
[STAThread]
static void Main()
{
if (!SingleInstance.Start()) {
SingleInstance.ShowFirstInstance();
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try {
MainForm mainForm = new MainForm();
Application.Run(mainForm);
} catch (Exception e) {
MessageBox.Show(e.Message);
}
SingleInstance.Stop();
}
}
//And secondly within your main form, the following code must be added:
protected override void WndProc(ref Message message)
{
if (message.Msg == SingleInstance.WM_SHOWFIRSTINSTANCE) {
Show
Window();
}
base.WndProc(ref message);
}
public void ShowWindow()
{
// Insert code here to make your form show itself.
WinApi.ShowToFront(this.Handle);
}
You can use the Threading Mutex and user32.dll
try this
Step 1 :
Declare the following constantes:
private const int SW_NORMAL = 1; // see WinUser.h for definitions
private const int SW_SHOWMAXIMIZED = 3;
private const int SW_RESTORE = 9;
[DllImport("User32", EntryPoint = "FindWindow")]
static extern IntPtr FindWindow(string className, string windowName);
[DllImport("User32", EntryPoint = "SendMessage")]
private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32", EntryPoint = "SetForegroundWindow")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("User32", EntryPoint = "SetWindowPlacement")]
private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
[DllImport("User32", EntryPoint = "GetWindowPlacement")]
private static extern bool GetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
private struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
}
Step 2 :
Add this methode :
public void application_run(Form form1)
{
bool createdNew;
System.Threading.Mutex m = new System.Threading.Mutex(true, form1.Name, out createdNew);
if (!createdNew)
{
MessageBox.Show("...", "...", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);//Alert message
try
{
// see if we can find the other app and Bring it to front
IntPtr hWnd = FindWindow(null, form1.Text);
if (hWnd != IntPtr.Zero)
{
LoaderDomain.WINDOWPLACEMENT placement = new LoaderDomain.WINDOWPLACEMENT();
placement.length = Marshal.SizeOf(placement);
GetWindowPlacement(hWnd, ref placement);
placement.showCmd = SW_SHOWMAXIMIZED;
SetWindowPlacement(hWnd, ref placement);
SetForegroundWindow(hWnd);
}
}
catch
{
//rien
}
}
else
{
Application.Run(form1);
}
// keep the mutex reference alive until the normal termination of the program
GC.KeepAlive(m);
}
Step 3 :
Replace in the main
Application.run(forms);
by a call to previous the methode

Categories