When i googled to find the way to change the window style i could find the code in "C" language
How can i use the snippet below in my c# application, so that i can hide the Title Bar of external application ? I have not used "C" before..
//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);
//assorted constants needed
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
/*
This function sets the parent of the window with class
ClassClass to the form/control the method is in.
*/
public void Reparent()
{
//get handle of parent form (.net property)
IntPtr par = this.Handle;
//get handle of child form (win32)
IntPtr child = FindWindow("ClassClass", null);
//set parent of child form
SetParent(child, par);
//get current window style of child form
int style = GetWindowLong(child, GWL_STYLE);
//take current window style and remove WS_CAPTION from it
SetWindowLong(child, GWL_STYLE, (style & ~WS_CAPTION));
}
I'm not a P/Invoke exprert, but looking at: http://www.pinvoke.net/default.aspx/coredll/SetWindowLong.html I guess you can call SetWindowLong to change window style without reparent.
For the window search you can try this:
Process[] processes = Process.GetProcessesByName("notepad.exe");
foreach (Process p in processes)
{
IntPtr pFoundWindow = p.MainWindowHandle;
// now you have the window handle
}
The snippet you have posted is in C#, not in C. You should be able to just add that code to your form and call the Reparent method. (Assuming you are using WinForms)
Note that the Reparent method will not only change the window style, but will also attempt to parent the window as a child of your window.
Related
Hi I'm developing an application that parsing data then after that I want to visualize some data on map using MapInfo, I made a MapInfo instance correctly but till now I do not know how to display data on the instance or how to use it also the instance I've created is not visible even after I make visible.
below is my code
namespace JA3_Trace_Viewer
{
public partial class JA3Main : Form
{
public JA3Main()
{
InitializeComponent();
}
private void JA3Main_Load(object sender, EventArgs e)
{
MapInfo.MapInfoApplication mapinfoinstance = new MapInfo.MapInfoApplication();
mapinfoinstance.Visible = true;
DDockWindow winM = new DDockWindow();
winM.Activate();
}
}
The data that I want to visualize on map is longitude and latitude and another columns lets call them data, so please if you help me.
Thanks in advance.
The new code:
public partial class Form1 : Form
{
// Sets the parent of a window.
[DllImport("User32", CharSet = CharSet.Auto, ExactSpelling = true)]
internal static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndParent);
//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);
//assorted constants needed
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_MAXIMIZE = 0x1000000;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Create a new instance of MapInfo.
MapInfoApplication mapinfo = new MapInfoApplication();
// Get the handle to the whole MapInfo application.
// 9 = SYS_INFO_MAPINFOWND.
string handle = mapinfo.Eval("SystemInfo(9)");
// Convert the handle to an IntPtr type.
IntPtr oldhandle = new IntPtr(Convert.ToInt32(handle));
//Make mapinfo visible otherwise it won't show up in our control.
mapinfo.Visible = true;
//Set the parent of MapInfo to a picture box on the form.
SetParent(oldhandle, this.pictureBox1.Handle);
//Get current window style of MapInfo window
int style = GetWindowLong(oldhandle, GWL_STYLE);
//Take current window style and remove WS_CAPTION(title bar) from it
SetWindowLong(oldhandle, GWL_STYLE, (style & ~WS_CAPTION));
//Maximize MapInfo so that it fits into our control.
mapinfo.Do("Set Window 1011 Max");
}
}
Class MapInfoApplication has a method called Do() and Eval(), there you can pass a command string, e.g. mapinfoinstance.Do('Open Table foo_bar.TAB as foo')
Have look at MapBasic samples in folder Samples\DOTNET\... in your MapBasic folder.
Im trying to create a program where I can send some process id of a process (that may be firefox, ie, notepad etc) to a method that scrolls window of the process.
I have been trying with GetScrollBarInfo and SetScrollPos which I found at pinvoke without any success. Im not sure if this is the right way or not. I started playing with GetScrollBarInfo, but it doesn't seem to work.
I tried the code found at http://www.pinvoke.net/default.aspx/user32.getscrollbarinfo
[StructLayout(LayoutKind.Sequential)]
public struct SCROLLBARINFO
{
public int cbSize;
public Rectangle rcScrollBar;
public int dxyLineButton;
public int xyThumbTop;
public int xyThumbBottom;
public int reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public int[] rgstate;
}
private const uint OBJID_HSCROLL = 0xFFFFFFFA;
private const uint OBJID_VSCROLL = 0xFFFFFFFB;
private const uint OBJID_CLIENT = 0xFFFFFFFC;
private int Scroll(int ProcessID)
{
IntPtr handle = Process.GetProcessById(ProcessID).MainWindowHandle;
SCROLLBARINFO psbi = new SCROLLBARINFO();
psbi.cbSize = Marshal.SizeOf(psbi);
int nResult = GetScrollBarInfo(handle, OBJID_CLIENT, ref psbi);
if (nResult == 0)
{
int nLatError = Marshal.GetLastWin32Error();
}
}
GetLastWin32Error() returns errorcode 122 which means "The data area passed to a system call is too small", according to http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
Im not sure what I do wrong. How can I solve this?
You could send a WM_MOUSEWHEEL message to do what you want. For example, to scroll down once in a new notepad window using C++:
HWND hwnd = FindWindowEx(FindWindow(NULL, "Untitled - Notepad"), NULL, "Edit", NULL);
RECT r;
GetClientRect(hwnd, &r);
SendMessage(hwnd, WM_MOUSEWHEEL, MAKEWPARAM(0, WHEEL_DELTA * -1), MAKELPARAM(r.right / 2, r.bottom / 2));
To adapt that to C#, you could do something such as this:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, ref Point lParam);
private void ScrollWindow(IntPtr hwnd, Point p, int scrolls = -1)
{
SendMessage(hwnd, WM_MOUSEWHEEL, (WHEEL_DELTA * scrolls) << 16, ref p);
}
Which could be used to scroll down once in a new notepad window like this:
//Imports
[DllImport("user32.dll", SetLastError = true)]
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);
...
//Actual code
IntPtr hwnd = FindWindowEx(FindWindow(null, "Untitled - Notepad"), IntPtr.Zero, "Edit", null);
Point p = new Point(0, 0);
ScrollWindow(hwnd, p);
Some programs will require the lParam sent to be a point that's actually above the scrolled area, while others such as notepad will not.
If you're trying to scroll the window of another process, you need to, in effect, simulate clicks on the scroll bar or key presses. The cleanest way to do that is to use UI Automation, which has both .NET and native interfaces.
By asking for the scrollbar info, you're simply getting information about how the scrollbar is displayed. That's not going to give you a way to scroll the window content. You have to get the target application to scroll the content by making it think the user is operating the scrollbar.
http://forums.codeguru.com/showthread.php?446352-How-to-scroll-active-window-SendMessage&p=1686041#post1686041
Final Code
class Program
{
[DllImport("user32.dll")]
static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui);
[DllImport("user32.dll")]
public static extern int SetScrollPos(IntPtr hWnd, System.Windows.Forms.Orientation nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public struct GUITHREADINFO
{
public int cbSize;
public int flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
public System.Drawing.Rectangle rcCaret;
}
const Int32 WM_VSCROLL = 0x0115;
const Int32 SB_LINERIGHT = 1;
static void Main(string[] args)
{
//create process in focus
Process.Start("notepad++", "Source.cpp");
Thread.Sleep(1000);
GUITHREADINFO threadInfo = new GUITHREADINFO();
threadInfo.cbSize = Marshal.SizeOf(threadInfo);
GetGUIThreadInfo(0, ref threadInfo);
SendMessage(threadInfo.hwndFocus, WM_VSCROLL, SB_LINERIGHT, 0);
//SetScrollPos not work. Change only scrollbar without scroll window
//SetScrollPos(threadInfo.hwndFocus, System.Windows.Forms.Orientation.Vertical, 10, true);
}
}
How can I close a window of external application programmatically in VB.net.
I just want to close the current window without closing the whole process.
use FindWindow and SendMessage APIs
here in C#, should be trivial to convert:
using Microsoft.Win32;
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName,string lpWindowName);
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
private void closeWindow()
{
// retrieve the handler of the window
int iHandle = FindWindow("Notepad", "Untitled - Notepad");
if (iHandle > 0)
{
// close the window using API
SendMessage(iHandle, WM_SYSCOMMAND, SC_CLOSE, 0);
}
}
source: http://www.codeproject.com/KB/dialog/closewindow.aspx
How can I prevent WPF window from minimizing when users clicks on show desktop button?
This link will help you : Get the minimize box click of a WPF window
you need to catch the event and handle it yourself.
Edit : This method will alert you once the state is changed, so it might not be the "best" solution but it could work.
Windows are not minimized when "Show Desktop" is issued. Instead the "WorkerW" and "Desktop" windows are brought to the foreground.
I ended up developing my own solution.
I scoured the internet for weeks trying to find an answer so I'm kind of proud of this one.
So what we do is use pinvoke to create a hook for the EVENT_SYSTEM_FOREGROUND window event.
This event triggers whenever the foreground window is changed.
Now what I noticed is when the "Show Desktop" command is issued, the WorkerW window class becomes foreground.
Note this WorkerW window is not the desktop and I confirmed the hwnd of this WorkerW window is not the Desktop hwnd.
So what we do is whenever the WorkerW window becomes the foreground, we set our "WPF Gadget Window" to be topmost!
Whenever a window other the WorkerW window becomes the foreground, we remove topmost from our "WPF Gadget Window".
If you want to take it a step further, you can uncomment out the part where I check if the new foreground window is also "PROGMAN", which is the Desktop window.
However, this will lead to your window becoming topmost if the user clicks their desktop on a different monitor. In my case, I did not want this behavior, but I figured some of you might.
Confirmed to work in Windows 10. Should work in older versions of Windows.
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
namespace YourNamespace
{
internal static class NativeMethods
{
[DllImport("user32.dll")]
internal static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, ShowDesktop.WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
internal static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
internal static extern int GetClassName(IntPtr hwnd, StringBuilder name, int count);
}
public static class ShowDesktop
{
private const uint WINEVENT_OUTOFCONTEXT = 0u;
private const uint EVENT_SYSTEM_FOREGROUND = 3u;
private const string WORKERW = "WorkerW";
private const string PROGMAN = "Progman";
public static void AddHook(Window window)
{
if (IsHooked)
{
return;
}
IsHooked = true;
_delegate = new WinEventDelegate(WinEventHook);
_hookIntPtr = NativeMethods.SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, _delegate, 0, 0, WINEVENT_OUTOFCONTEXT);
_window = window;
}
public static void RemoveHook()
{
if (!IsHooked)
{
return;
}
IsHooked = false;
NativeMethods.UnhookWinEvent(_hookIntPtr.Value);
_delegate = null;
_hookIntPtr = null;
_window = null;
}
private static string GetWindowClass(IntPtr hwnd)
{
StringBuilder _sb = new StringBuilder(32);
NativeMethods.GetClassName(hwnd, _sb, _sb.Capacity);
return _sb.ToString();
}
internal delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
private static void WinEventHook(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
if (eventType == EVENT_SYSTEM_FOREGROUND)
{
string _class = GetWindowClass(hwnd);
if (string.Equals(_class, WORKERW, StringComparison.Ordinal) /*|| string.Equals(_class, PROGMAN, StringComparison.Ordinal)*/ )
{
_window.Topmost = true;
}
else
{
_window.Topmost = false;
}
}
}
public static bool IsHooked { get; private set; } = false;
private static IntPtr? _hookIntPtr { get; set; }
private static WinEventDelegate _delegate { get; set; }
private static Window _window { get; set; }
}
}
You can change your window's parent to not be affected by Show Desktop. (as stated here: Window "on desktop")
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Loaded += MainWindowLoaded;
}
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void MainWindowLoaded(object sender, RoutedEventArgs e)
{
var hwnd = new WindowInteropHelper(this).Handle;
var ProgmanHwnd = FindWindowEx(FindWindowEx(FindWindow("Progman", "Program Manager"), IntPtr.Zero, "SHELLDLL_DefView",""), IntPtr.Zero,"SysListView32", "FolderView");
SetParent(hwnd, ProgmanHwnd);
}
}
I need to disable the Mouse Clicks, Mouse movement for a specific windows for a Kiosk application. Is it Feasible in C# ?
I have removed the menu bar and title bar of a specific window, will that be a starting point to achieve the above requirement ? How can i achieve this 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));
}
}
}
It sounds like you are looking for EnableWindow. The description is:
Enables or disables mouse and keyboard
input to the specified window or
control. When input is disabled, the
window does not receive input such as
mouse clicks and key presses. When
input is enabled, the window receives
all input.
So you would add
[DllImport("user32.dll")]
static extern bool EnableWindow(IntPtr hWnd, bool enable);
and
EnableWindow(pFoundWindow, false);
This is equivalent to setting the Enabled property on a Windows Forms Form/Control.
You can try to override the WndProc and check for WM_MOUSE* events there. If you dont call the base WndProc for these handled events, it should work.
A point to consider here is that since yours is a kiosk application, will your special mouse handling lead to any problems for Touch screen.
To prevent keyboard input in a window in another process, you need to make a keyboard hook.
You can then check GetForegroundWindow() and suppress the input.