Modify the windows style of another application using winAPI - c#

My application starts up another application. whereby, i want to remove the title bar of the application which is started using c#.
How can i do this, starting up with the piece of code below ?
//Get current style
lCurStyle = GetWindowLong(hwnd, GWL_STYLE)
//remove titlebar elements
lCurStyle = lCurStyle And Not WS_CAPTION
lCurStyle = lCurStyle And Not WS_SYSMENU
lCurStyle = lCurStyle And Not WS_THICKFRAME
lCurStyle = lCurStyle And Not WS_MINIMIZE
lCurStyle = lCurStyle And Not WS_MAXIMIZEBOX
//apply new style
SetWindowLong hwnd, GWL_STYLE, lCurStyle
//reapply a 3d border
lCurStyle = GetWindowLong(hwnd, GWL_EXSTYLE)
SetWindowLong hwnd, GWL_EXSTYLE, lCurStyle Or WS_EX_DLGMODALFRAME
//redraw
SetWindowPos hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_FRAMECHANGED

#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));
}
}
}

Related

Process frozen when I try to start it hooked to a panel

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);
}

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.

Window on top of everything like mouse cursor

I am programming a mouse cursor to be used in the operating system that has motion blur on Windows 10. I decided to use Unity3D for this because of Unity3D has very powerful in terms of effects and hardware rendering. I coded an overlay window to be rendered as top most. However, context menus on any application are getting rendered on top of the window and the objects on the form are getting behind the context menu. Is there a way to achieve this? I don't need to use Unity3D for this so any suggestions are welcome.
Here is the code I wrote for the window.
using System;
using System.Runtime.InteropServices;
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class TransparentWindow : MonoBehaviour
{
private struct MARGINS
{
public int cxLeftWidth;
public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight;
}
// Define function signatures to import from Windows APIs
[DllImport("user32.dll")]
private static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("Dwmapi.dll")]
private static extern uint DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margins);
[DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")]
static extern int SetLayeredWindowAttributes(IntPtr hwnd, int crKey, byte bAlpha, int dwFlags);
[DllImport("user32.dll", EntryPoint = "SetWindowPos")]
private static extern int SetWindowPos(IntPtr hwnd, int hwndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
// Definitions of window styles
const int GWL_STYLE = -16;
const uint WS_POPUP = 0x80000000;
const uint WS_VISIBLE = 0x10000000;
const uint WS_EX_LAYERED = 0x00080000;
const uint WS_EX_TRANSPARENT = 0x00000020;
const uint WS_EX_TOPMOST = 0x00000008;
const int HWND_TOPMOST = -1;
const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_NOZORDER = 0x0004;
const UInt32 SWP_NOREDRAW = 0x0008;
const UInt32 SWP_NOACTIVATE = 0x0010;
const UInt32 SWP_FRAMECHANGED = 0x0020;
const UInt32 SWP_SHOWWINDOW = 0x0040;
const UInt32 SWP_HIDEWINDOW = 0x0080;
const UInt32 SWP_NOCOPYBITS = 0x0100;
const UInt32 SWP_NOOWNERZORDER = 0x0200;
const UInt32 SWP_NOSENDCHANGING = 0x0400;
const UInt32 SWP_DRAWFRAME = SWP_FRAMECHANGED;
const UInt32 SWP_NOREPOSITION = SWP_NOOWNERZORDER;
const UInt32 SWP_DEFERERASE = 0x2000;
const UInt32 SWP_ASYNCWINDOWPOS = 0x4000;
// This static method is required because legacy OSes do not support
// SetWindowLongPtr
public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, uint dwNewLong)
{
if (IntPtr.Size == 8)
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
else
return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
}
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, uint dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, uint dwNewLong);
void Start()
{
#if !UNITY_EDITOR // You really don't want to enable this in the editor..
int fWidth = Screen.width;
int fHeight = Screen.height;
var margins = new MARGINS() { cxLeftWidth = -1 };
var hwnd = GetActiveWindow();
SetWindowLong(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
SetWindowLongPtr(hwnd, -20, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT); // GWL_EXSTYLE -20
SetLayeredWindowAttributes(hwnd, 0, 255, 2);
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
DwmExtendFrameIntoClientArea(hwnd, ref margins);
#endif
}
void OnRenderImage(RenderTexture from, RenderTexture to)
{
Graphics.Blit(from, to, m_Material);
}
}
Here is the screenshot animation shows my issue. Please see the second mouse cursor in this screenshot which follows operating system's mouse cursor:

Toggle Between Fullscreen and Windowed Mode

I'm trying to change the game window from fullscreen to windowed mode and from windowed to fullscreen.
From windowed to fullscreen mode works fine, but from fullscreen to windowed mode does not work. So why? And how I can fix that?
[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
static extern IntPtr FindWindowByCaption(IntPtr zeroOnly, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, long dwNewLong);
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, long dwNewLong)
{
return IntPtr.Size == 8
? SetWindowLongPtr64(hWnd, nIndex, dwNewLong)
: new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, WindowShowStyle nCmdShow);
// Works perfectly
public static void SetFullScreenMode(string windowName)
{
IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, windowName);
SetWindowLongPtr(hWnd, GWL_STYLE, WS_VISIBLE | WS_CLIPSIBLINGS);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_TOPMOST);
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
}
// Does not work. Nothing happening when I call this method
public static void SetWindowedMode(string windowName)
{
IntPtr hWnd = FindWindowByCaption(IntPtr.Zero, windowName);
SetWindowLongPtr(hWnd, GWL_STYLE, WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
SetWindowLongPtr(hWnd, GWL_EXSTYLE, WS_EX_WINDOWEDGE);
SetWindowPos(hWnd, (IntPtr) 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
}

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.

Categories