Its possible remove a window console title bar using c# and windows api, if yes howto? Please.
This simple app hides and shows the title bar of the console that it's in. It changes the console title to a guid momentarily to find the window handle. Afterwards it uses ToggleTitleBar to show or hide using the found handle.
public class Program
{
public static void ToggleTitleBar(long hwnd, bool showTitle)
{
long style = GetWindowLong(hwnd, -16L);
if (showTitle)
style |= 0xc00000L;
else
style &= -12582913L;
SetWindowLong(hwnd, -16L, style);
SetWindowPos(hwnd, 0L, 0L, 0L, 0L, 0L, 0x27L);
}
public static void Main()
{
Guid guid = Guid.NewGuid();
string oldTitle = Console.Title;
Console.Title = guid.ToString();
int hwnd = FindWindow("ConsoleWindowClass", guid.ToString());
Console.Title = oldTitle;
Console.WriteLine("Press enter to hide title");
Console.ReadLine();
ToggleTitleBar(hwnd, false);
Console.WriteLine("Press enter to show title");
Console.ReadLine();
ToggleTitleBar(hwnd, true);
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
[DllImport("user32", EntryPoint = "GetWindowLongA")]
public static extern long GetWindowLong(long hwnd, long nIndex);
[DllImport("user32", EntryPoint = "SetWindowLongA")]
public static extern long SetWindowLong(long hwnd, long nIndex, long dwNewLong);
[DllImport("user32")]
public static extern long SetWindowPos(long hwnd, long hWndInsertAfter, long x, long y, long cx, long cy,
long wFlags);
[DllImport("User32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
}
Edit: Sorry, I see that you're looking for a solution for a console application. No, there is no way I know of to do what you're trying to do. It is also not simple to host a console in a WinForms application.
However, if you ARE using a WinForms application or WPF, consider the following.
this.ControlBox = false;
this.Text = string.Empty;
Otherwise, you could set FormBorderStyle to None.
You can also hide the program from the task bar if you need to.
this.ShowInTaskBar = false;
This will probably not work. In theory you could use something like this:
HWND handle = FindWindow(L"ConsoleWindowClass", NULL);
LONG style = GetWindowLong(handle, GWL_STYLE);
style = style & ~WS_CAPTION;
SetWindowLong(handle, GWL_STYLE, style);
This will work for every window except console windows. SetWindowLong returns 0, and GetLastError returns 5 (Access denied), even if you run the application as administrator.
I have some (very) old code I think somehow related; I'd to display Microsoft Excel inside a winform application:
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern int SetParent(int hWndChild, int hWndNewParent);
[DllImport("user32.dll")]
public static extern int MoveWindow(
int hWnd, int x, int y,
int nWidth, int nHeight, int bRepaint);
//
private static int hwnExcel = 0;
private System.Windows.Forms.PictureBox picContainer;
// ...
private void Principal_Resize(object sender, EventArgs e)
{
picContainer.Width = this.Width - 8;
picContainer.Height = this.Height - 45;
User32.SetParent(hwnExcel, 0);
User32.MoveWindow(
hwnExcel, 0, 0,
picContainer.Width, picContainer.Height, 1);
}
use FindWindow to get the handle of the console window then SetWindowLong to modify his properties
Related
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);
I'm trying to embed the osk in a wpf window or a user control and I've found the code below and it's working for notepad but for tabtip.exe, it's saying that it doesn't have a graphical interface??
WaitForInputIdle failed. This could be because the process does not have a graphical interface.
I tried letting it sleep for awhile instead of calling waitForInputIdle method but it throws another exception:
Process has exited, so the requested information is not available.
But in my task manager, I can still see TabTip.exe running.
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private System.Windows.Forms.Panel _panel;
private Process _process;
public MainWindow()
{
InitializeComponent();
_panel = new System.Windows.Forms.Panel();
windowsFormsHost1.Child = _panel;
}
[DllImport("user32.dll")]
private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr hWnd, IntPtr hWndParent);
[DllImport("user32")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
private const int SWP_NOZORDER = 0x0004;
private const int SWP_NOACTIVATE = 0x0010;
private const int GWL_STYLE = -16;
private const int WS_CAPTION = 0x00C00000;
private const int WS_THICKFRAME = 0x00040000;
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
if (_process != null)
{
_process.Refresh();
_process.Close();
}
}
private void ResizeEmbeddedApp()
{
if (_process == null)
return;
SetWindowPos(_process.MainWindowHandle, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
}
protected override Size MeasureOverride(Size availableSize)
{
Size size = base.MeasureOverride(availableSize);
ResizeEmbeddedApp();
return size;
}
private void button1_Click_1(object sender, RoutedEventArgs e)
{
button1.Visibility = Visibility.Hidden;
ProcessStartInfo psi = new ProcessStartInfo("C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe");
_process = Process.Start(psi);
Thread.Sleep(500);
//_process.WaitForInputIdle();
SetParent(_process.MainWindowHandle, _panel.Handle);
// remove control box
int style = GetWindowLong(_process.MainWindowHandle, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(_process.MainWindowHandle, GWL_STYLE, style);
// resize embedded application & refresh
ResizeEmbeddedApp();
}
}
}
Edit: Inspired by rene's comment, I've tried to obtain the window ptr as below and used spy++ to verify that the address that FindWindow gives is pointing to the correct window, but it's still not moving:
IntPtr KeyboardWnd = FindWindow("IPTip_Main_Window", null);
int style = GetWindowLong(KeyboardWnd, GWL_STYLE);
style = style & ~WS_CAPTION & ~WS_THICKFRAME;
SetWindowLong(KeyboardWnd, GWL_STYLE, style);
SetWindowPos(KeyboardWnd, IntPtr.Zero, 0, 0, (int)_panel.ClientSize.Width, (int)_panel.ClientSize.Height, SWP_NOZORDER | SWP_NOACTIVATE);
Edit 2: My first thought was that tab tip couldn't be resized, but then I noticed a behavior when I try to move the window across two different screen, it'll resize to fit the screen size, so I'm sure there must be a way to resize, so I started spy++(x64) to check :
Edit 3: after tinkering abit with user32 api and no progress, I've tried to use a memory scanner to scan for the x and y position of tabtip and change it, however, it's not refreshing until a repaint is triggered, I'm wondering the feasibility going down that path.
Can you try to run your handle code in STA thread? I had a similar issue with native window, which I had resolved using STA thread.
var thread = new Thread(() => {
// Your code here
});
thread.TrySetApartmentState(ApartmentState.STA);
thread.Start();
I had a similar problem, and the reason I had it was that I started a program that needed to be run by an administrator with a non-administrative program, and it would pop up with WaitForInputIdle failed. This could be because the process does not have a graphical interface, so I assume you try starting your program with an administrator
How can I get the Window Title that the user currently have focus on?
I'm making a program that runs with another Window, and if the user does not have focus on that window I find no reason for my program to keep updating.
So how can I determine what window the user have focus on?
I did try to look into
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
but I seems I can only use that if the Window is part of my application which is it not.
Check this code:
[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;
}
Use GetForegroundWindow to retrieve the handle of the focused window and GetWindowText to get the window title.
[ DllImport("user32.dll") ]
static extern int GetForegroundWindow();
[ DllImport("user32.dll") ]
static extern int GetWindowText(int hWnd, StringBuilder text, int count);
static void Main() {
StringBuilder builder = new StringBuilder(255) ;
GetWindowText(GetForegroundWindow(), builder, 255) ;
Console.WriteLine(builder) ;
}
I am developing an application in c#.net,and for that i am writing code to display icon in a system tray,and whenever a new message arrives the balloon tooltip will be shown there,which has click event which will open new message arrived,everything works fine,but the problem is i am getting multiple numbers of icon generated in system tray,which shuld be only one,how can i prevent it?i found on internet how to dispose them,but couldn't find way to prevent more than one.or is there any better way to show notifications for newly received message..please help me if you know the solution..
There are better custom solutions available see here and here for some examples.
However, System Tray doesn't refresh automatically. If you show/hide multiple system tray icons, it can mess the tray up. Normally all disposed icons will disappear when you mouse hover. However, there is a way to refresh the system tray programmatically. Reference here.
Note : SendMessage function, sends the specified message to a window or windows. The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);
public void RefreshTrayArea()
{
IntPtr systemTrayContainerHandle = FindWindow("Shell_TrayWnd", null);
IntPtr systemTrayHandle = FindWindowEx(systemTrayContainerHandle, IntPtr.Zero, "TrayNotifyWnd", null);
IntPtr sysPagerHandle = FindWindowEx(systemTrayHandle, IntPtr.Zero, "SysPager", null);
IntPtr notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "Notification Area");
if (notificationAreaHandle == IntPtr.Zero)
{
notificationAreaHandle = FindWindowEx(sysPagerHandle, IntPtr.Zero, "ToolbarWindow32", "User Promoted Notification Area");
IntPtr notifyIconOverflowWindowHandle = FindWindow("NotifyIconOverflowWindow", null);
IntPtr overflowNotificationAreaHandle = FindWindowEx(notifyIconOverflowWindowHandle, IntPtr.Zero, "ToolbarWindow32", "Overflow Notification Area");
RefreshTrayArea(overflowNotificationAreaHandle);
}
RefreshTrayArea(notificationAreaHandle);
}
private static void RefreshTrayArea(IntPtr windowHandle)
{
const uint wmMousemove = 0x0200;
RECT rect;
GetClientRect(windowHandle, out rect);
for (var x = 0; x < rect.right; x += 5)
for (var y = 0; y < rect.bottom; y += 5)
SendMessage(windowHandle, wmMousemove, 0, (y << 16) + x);
}
I'm writing a .exe that is supposed to run as a scheduled task to check if I have required IE windows open running .Xbaps on specific monitors. I have code that checks what URL is supposed to run, if it's not I use this code to launch it, then move it to the correct monitor:
Process myProcess = Process.Start("iexplore.exe", "-new -k " + "http://server01:123/software.client.xbap");
myProcess.WaitForInputIdle();
Thread.Sleep(500);
MoveWindowToMonitor(myProcess.MainWindowHandle, 1);
Window Moving code:
private static void MoveWindowToMonitor(IntPtr windowHandler, int monitor)
{
RECT windowRec = new RECT();
GetWindowRect(windowHandler, ref windowRec);
int width = windowRec.Right - windowRec.Left;
int height = windowRec.Top - windowRec.Bottom;
if (width < 0)
width = width * -1;
if (height < 0)
height = height * -1;
SetWindowPos(windowHandler, (IntPtr)SpecialWindowHandles.HWND_TOP, Screen.AllScreens[monitor].WorkingArea.Left,
Screen.AllScreens[monitor].WorkingArea.Top, width, height, SetWindowPosFlags.SWP_SHOWWINDOW);
}
Running a quick test version of this gets the first IE window open, Xbap launched, and then quickly moves it over to my other monitor. When I run it a second time, without closing the first IE window, I always get InvalidOperationException
"Process has exited, so the requested information is not available."
I've checked my Task Manager as this is happening and I actually get two iexplore.exe items under details the first time I run the task, and only one additional iexplorer.exe for each subsequent execution of the task. I also get one PresentationHost.exe per xbap launched.
Anyone have any idea what I'm doing wrong or a better way to do this?
My end goal is to be able to do this:
Launch IE in Kiosk Mode on monitor 1 with specific url X:
Launch IE in Kiosk Mode on monitor 2 with specific url Y:
After you launch an IE process, it does some funny stuff and that process you have launched can occasionally end right away as another takes over the window.
What I would do is, using the methods below, is EnumTheWindows which would step through every visible window running and look for Internet Explorer or my baseURL. Then I would pass that Window Handle to GetURL and get the specific URL that IE window was running. This allowed me to use ConfirmProcessIsOnProperMonitor() and MoveWindowToMonitor() to get the windows on the proper monitor.
Important stuff:
private static bool ConfirmProcessIsOnProperMonitor(IntPtr windowHandler, int monitor)
{
//make sure you don't go to an incorrect monitor
if (monitor >= Screen.AllScreens.Count()) monitor = Screen.AllScreens.Count() - 1;
RECT windowRec = new RECT();
GetWindowRect(windowHandler, ref windowRec);
if (windowRec.Left != Screen.AllScreens[monitor].WorkingArea.Left || windowRec.Top != Screen.AllScreens[monitor].WorkingArea.Top)
return false;
else
return true;
}
private static void MoveWindowToMonitor(IntPtr windowHandler, int monitor)
{
//make sure you don't go to an incorrect monitor
if (monitor >= Screen.AllScreens.Count()) monitor = Screen.AllScreens.Count() - 1;
RECT windowRec = new RECT();
GetWindowRect(windowHandler, ref windowRec);
int width = windowRec.Right - windowRec.Left;
int height = windowRec.Top - windowRec.Bottom;
if (width < 0)
width = width * -1;
if (height < 0)
height = height * -1;
SetWindowPos(windowHandler, (IntPtr)SpecialWindowHandles.HWND_TOP, Screen.AllScreens[monitor].WorkingArea.Left,
Screen.AllScreens[monitor].WorkingArea.Top, width, height, SetWindowPosFlags.SWP_SHOWWINDOW);
}
protected static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
StringBuilder sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
string windowText = sb.ToString();
if (windowText.ToLower().Contains(_baseURL) || windowText.ToLower().Contains("internet explorer"))
{
string url = GetURL(hWnd);
_windowhandles.Add(hWnd, url);
}
}
return true;
}
private static string GetURL(IntPtr intPtr)
{
foreach (InternetExplorer ie in new ShellWindows())
{
if (ie.HWND == intPtr.ToInt32())
{
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(ie.FullName);
if ((fileNameWithoutExtension != null) && fileNameWithoutExtension.ToLower().Equals("iexplore"))
{
return ie.LocationURL;
}
else
{
return null;
}
}
}
return null;
}
Hard to read windows API code:
[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, StringBuilder msgbody);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, SetWindowPosFlags uFlags);
[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
protected delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
protected static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
protected static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
protected static extern bool IsWindowVisible(IntPtr hWnd);