Process frozen when I try to start it hooked to a panel - c#

I need to launch an external .exe application within my windows forms app on a panel. If I start the process, without placing it on the panel, it's fine but if I place it on the panel the program freezes and does nothing.
I tried to google the problem but I did not find anything,can you help me?.
[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")]
static extern bool MoveWindow(IntPtr Handle, int x, int y, int w, int h, bool repaint);
[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;
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
private const int SW_SHOWMAXIMIZED = 3;
string projectDirectory = "C:\\Users\\anten\\OneDrive\\Desktop\\together\\VisualSharp7\\bin\\Debug";
Visual_Sharp7.StartInfo.WorkingDirectory = projectDirectory;
Visual_Sharp7.StartInfo.FileName = "VisualSharp7.exe";
if (Visual_Sharp7.Start())
{
IntPtr ptr = IntPtr.Zero;
while ((ptr = Visual_Sharp7.MainWindowHandle) == IntPtr.Zero) ;
int WS_VISIBLE = GetWindowLong(Visual_Sharp7.MainWindowHandle, GWL_STYLE);
SetWindowLong(Visual_Sharp7.MainWindowHandle, GWL_STYLE, (WS_VISIBLE & ~WS_CAPTION));
SetParent(Visual_Sharp7.MainWindowHandle, panelMain.Handle);
ShowWindow(Visual_Sharp7, SW_SHOWMAXIMIZED);
}

Related

Process that started in an MDI Container stays always on top

I am working on a Winforms product. This product has an MDI main window, data presentation forms and a software that is developed for this project which is started in the Main Window if the related button is clicked. The software is called as a process when the button is clicked and it's parent is set to the main window. Let's say the software is the TeraTerm for the demonstration.
private void barButtonItem2_ItemClick(object sender, ItemClickEventArgs e)
{
Process p2 = new Process();
ProcessStartInfo ps2 = new ProcessStartInfo(#"C:\Program Files (x86)\teraterm\ttermpro.exe", "");
p2 = Process.Start(ps2);
p2.EnableRaisingEvents = true;
var processResult = p2.WaitForInputIdle(10000); // Allow the process to open it's window
appWin1 = p2.MainWindowHandle;
// Put it into this form
Utilities.HideMinimizeButton(p2.MainWindowHandle);
Utilities.SetWindowPos(p2.MainWindowHandle, Utilities.HWND_BOTTOM, 0, 0, 0, 0, Utilities.SETPOS_FLAGS);
Utilities.SetParent(p2.MainWindowHandle, this.Handle);
}
Utilities class is basically a dll import class for the window handling of the processes. Its code is:
public static class Utilities
{
public static int GWL_STYLE = -16;
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 readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
public static readonly IntPtr HWND_TOP = new IntPtr(0);
public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
public const UInt32 SWP_NOSIZE = 0x0001;
public const UInt32 SWP_NOOWNERZORDER = 0x0200;
public const UInt32 SWP_NOMOVE = 0x0002;
public const UInt32 SWP_SHOWWINDOW = 0x0040;
public const UInt32 SWP_NOZORDER = 0x0040;
public const UInt32 SETPOS_FLAGS = SWP_NOSIZE | SWP_SHOWWINDOW;
public const int SW_MAXIMIZE = 3;
public const int SW_MINIMIZE = 6;
public const int SW_SHOWDEFAULT = 10;
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
[DllImport("user32.dll")]
internal extern static int SetWindowLong(IntPtr hwnd, int index, int value);
[DllImport("user32.dll")]
internal extern static int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
internal static void HideMinimizeAndMaximizeButtons(IntPtr hwnd)
{
const int GWL_STYLE = -16;
const long WS_MINIMIZEBOX = 0x00020000L;
const long WS_MAXIMIZEBOX = 0x00010000L;
long value = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (int)(value & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX));
}
internal static void HideMinimizeButton(IntPtr hwnd)
{
const int GWL_STYLE = -16;
const long WS_MINIMIZEBOX = 0x00020000L;
const long WS_MAXIMIZEBOX = 0x00010000L;
long value = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (int)(value & ~WS_MINIMIZEBOX));
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
}
This code is works to put my process as an MDI child. The problem is; the process window is always top of the every child form. I tried calling SetWindowPos with HWND_BOTTOM but no luck.
You may see from here and here the process is at the top even it is not activated.
I achieved success using most of the code you used. Here is my image:
There are a number of minor but obviously important issues in your posted code, making it impossible to know what you're actually doing that is causing the error.
You call the HideMinimizeButton method but do not provide its definition. In my working code, I called the HideMinimizeAndMaximizeButtons method you expose in your Utilities class.
You omitted your static extern for GetWindowsLong and SetWindowLong, so we can't see what you did there...
Your SetWindowLong call in your utilities class tries to cast the final argument to int when the SetWindowsLong WinAPI function I see says that it should be uint.
My version of your Utilities class looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp8
{
class Utilities
{
public static readonly IntPtr HWND_TOPMOST = new IntPtr(-1);
public static readonly IntPtr HWND_NOTOPMOST = new IntPtr(-2);
public static readonly IntPtr HWND_TOP = new IntPtr(0);
public static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
public const UInt32 SWP_NOSIZE = 0x0001;
public const UInt32 SWP_NOOWNERZORDER = 0x0200;
public const UInt32 SWP_NOMOVE = 0x0002;
public const UInt32 SWP_SHOWWINDOW = 0x0040;
public const UInt32 SWP_NOZORDER = 0x0040;
public const UInt32 SETPOS_FLAGS = SWP_NOOWNERZORDER | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE;
[DllImport("user32")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
internal static void HideMinimizeAndMaximizeButtons(IntPtr hwnd)
{
const int GWL_STYLE = -16;
const long WS_MINIMIZEBOX = 0x00020000L;
const long WS_MAXIMIZEBOX = 0x00010000L;
long value = GetWindowLong(hwnd, GWL_STYLE);
SetWindowLong(hwnd, GWL_STYLE, (uint)(value & ~WS_MINIMIZEBOX & ~WS_MAXIMIZEBOX));
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
}
}
Clearly, this works for me. If it works for you too, kindly accept as the answer.

SetParent() resizing main form

I am using SetParent() to embed my form on an existing window.
It works fine but when I move the existing window, my form gets resized to existing window's size. So for example if my form's size is 300x200 and the windows size is 800x800, once I move(drag) the window, my form gets resized to the window's size(800x800).
Is there a way to avoid that?
This is my code:
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
public static int GWL_STYLE = -16;
public static int WS_CHILD = 0x40000000;
//my call of the methods
SetWindowLong(this.Handle, GWL_STYLE, GetWindowLong(this.Handle, GWL_STYLE) | WS_CHILD);
SetParent(this.Handle, GetHandle());

Set transparency to a control in windows form

I am new in programming. I can’t find a way to set transparency to a control. Please help. Something like, Form.transparency or some thing else.
The most simple way to make a form transparent is just to set the Form.Opacity property to a value.
Or, you can try, API calls for doing that,
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
public const int GWL_EXSTYLE = -20;
public const int WS_EX_LAYERED = 0x80000;
public const int LWA_ALPHA = 0x2;
public const int LWA_COLORKEY = 0x1;
For Calling,
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) ^ WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0, 128, LWA_ALPHA);

Using Window Handle to disable Mouse clicks and Keyboard Inputs using P/Invoke

I need to disable the Mouse Clicks, Mouse movement and Keyboard Inputs for a specific windows for a Kiosk application. Is it feasible using .NET ?
I have removed the menu bar and title bar of a specific window, will that be a starting point to achieve the above requirement ?
The code for removing the menu bar and title bar using window handle :
#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)
{
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));
}
}
}
Use the EnableWindow API call to do this. I haven't used this in many years but I don't believe there are any cross process issues with this.

c#: SetScrollPos (user32.dll)

I want to have 2 (rich)texboxes (vc# 2k8) with same scrolling... so when I scroll tb1 the tb2 scrolls to the same position. I use this functions:
[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
public static extern int GetScrollPos(IntPtr hwnd, int nBar);
That works fine but
int pos = GetScrollPos(tb1.Handle, 1);
SetScrollPos(tb2.Handle, 1, pos, true);
only sets the scrollbar to the same position but down update the text in there.
tb2.Update() oder Refresh won't work...
Please help. Ty
I found answer
[DllImport("user32.dll")]
static extern int SetScrollPos(IntPtr hWnd, int nBar,
int nPos, bool bRedraw);
[DllImport("User32.Dll", EntryPoint = "PostMessageA")]
static extern bool PostMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public void ScrollTo(int Position) {
SetScrollPos((IntPtr)textBox1.Handle, 0x1, Position, true);
PostMessage((IntPtr)textBox1.Handle, 0x115, 4 + 0x10000 * Position, 0);
}

Categories