I need to add hooks to wpf windows for creating keyboard shortcuts to my application.
I'm trying to get the window pointer from the Application class when it's activated, using the activated event. It works great when there's only one window.
We allow opening another window by pressing F11. This window opens in full screen mode and it can be closed only by pressing F11 or ESC. It seems like I can't get the correct pointer of this new window because all keyboard shortcuts don't work, except for F11 for some reason.
Code for getting pointer:
var windows = System.
Windows.Application. Current.Windows;
If (windows.Count < 1)
{
return false;
}
else if (windows. Count ==1)
{
winPointer = new WindowInteropHelper(windows[0]);
return true;
}
else
{
for (int I = 0; I < windows. Count; I++)
{
if (windows [I].IsActive)
winPointer =new WindowInteropHelper(windows[i]);
.
.
.
I'm not sure if I'm missing something, but if you're opening a new window, why can't you capture the key down for that window and handle it that way?
public partial class NewFullScreenWindow : Window
{
public NewFullScreenWindow()
{
InitializeComponent();
KeyDown += HandleKeyDown;
}
private void HandleKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape || e.Key == Key.F11)
{
Close();
}
}
}
Related
when i move between forms buttons works as expected, but when im closing my custom pop up only seconds click on any button will trigger it
this is the code im using to load my custom popup
public void loadPopUp(Form from, Form to)
{
to.Tag = from;
to.Show(from);
}
and this is the code my using to close my custom popup
public void closePopUp(string formName)
{
for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
{
string name = Application.OpenForms[i].Name; //for debugging only
if (Application.OpenForms[i].Name == formName)
Application.OpenForms[i].Close();
}
}
note: this is not asp.net application
You should have something else in your code or you make something with the main window that changes the normal behavior of the forms engine. I have tried to build a sample app with LinqPAD using the code above and I have a normal behavior as expected. When I close the popup the focus is restored to the main form.
Nevertheless you could use the main form saved instance in the Tag property to call the Activate method and restore the focus to the main form.
public void closePopUp(string formName)
{
// No need to loop over all application OpenForms if you just want
// to close this popup
// for (int i = Application.OpenForms.Count - 1; i >= 0; i--)
// {
// string name = Application.OpenForms[i].Name; //for debugging only
// if (Application.OpenForms[i].Name == formName)
// Application.OpenForms[i].Close();
//}
var mainForm = this.Tag as Form;
this.Close();
if(mainForm != null)
mainForm.Activate();
}
Note, I use a cast to the base Form class, so your code doesn't depend on the popup created by a particular class instance. This is possible because Activate is a base class method.
I know there are lots of article over Google related to this, and believe me I have tried almost everything.
So the problem is, I have a wpf application in which when user focuses on any input control like textbox I am showing external touch keyboard using TabTip.exe.
Following code:
public class KeyboardHelper
{
private const string PROCESS_NAME = "TabTip";
private const string PROCESS_PATH = "Common Files/Microsoft Shared/ink/TabTip.exe";
public static void ShowKeyboard()
{
Process keyboard = null;
Process[] pname = Process.GetProcessesByName(PROCESS_NAME);
if (pname.Length == 0)
{
keyboard = new Process();
}
else
{
keyboard = pname[0];
}
string processPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), PROCESS_PATH);
keyboard.StartInfo.FileName = processPath;
keyboard.Start();
}
public static void Closekeyboard()
{
Process[] pname = Process.GetProcessesByName(PROCESS_NAME);
if (pname.Length > 0)
{
pname[0].Kill();
}
}
}
Now problem starts here keyboard open but if it is in docked mode, it causes my app to resize almost half of the screen. And when I close the keyboard app remains same in size, I want to restore to full screen state again.
Controlling my size from cs because it comes from a DB
WindowState = maximized;
ResizeMode= NoResize;
WindowsStyle = None;
Any work around to solve the issue.
I have tried UpdateLayout, Dispatcher.BeginInvoke, Invalidate methods.
Thanks Jason, now I know the cause or can say case scenario of the problem. In my app I have to decide the startup page at runtime, So I am using code like this
private void Application_Startup(object sender, StartupEventArgs e)
{
//Set startup page for the application.
MainWindow window = new MainWindow();
window.ShowDialog();
}
And this is the problem. If I use normal default way than everything works fine.
My application has several forms.
What I want to do is to be able to switch between them (and only between them) using a pair of predefined keys (say Keys.A + Keys.B), just like ALT + TAB does for Windows (windows are shown in foreground).
I tried getting the list of forms and then programmatically call Alt + Tab, but, as expected, this allows to switch between all open windows and not only the ones belonging to the application.
Thanks for any help!
You could implement IMessageFilter and add it to your Application, then globally process the messages of your application.
Here is how you do that.
public class MessageFilter : IMessageFilter
{
public bool PreFilterMessage(ref Message m)
{
switch ((WindowsMessage)m.Msg)
{
case WindowsMessage.WM_KEYDOWN:
case WindowsMessage.WM_SYSKEYDOWN:
{
if (((int)m.WParam | ((int)Control.ModifierKeys)) != 0)
{
Keys keyData = (Keys)(int)m.WParam;
var activeForm = Form.ActiveForm;
var forms = Application.OpenForms.Cast<Form>().Where(x => x.Visible).ToArray();
int active = Array.IndexOf(forms, activeForm);
if (keyData == Keys.A)
{
int next = (active + 1)%forms.Length;
forms[next].Activate();//Activate next
}
else if (keyData == Keys.B)
{
int prev = (active - 1) % forms.Length;
forms[prev].Activate();//Activate previous
}
break;
}
}
return false;
}
}
class MainForm : Form
{
protected override void OnLoad(EventArgs e)
{
Application.AddMessageFilter(new MessageFilter());
}
}
You can find WindowsMessage enumeration here.
If you have multiple windows (forms) opened and they have normal caption or belong to MDI, then Ctrl+F6 is a standard shortcut to switch between them.
Otherwise, making a hotkey, to switch between forms is pretty trivial task:
all forms have to have KeyPreview = true and KeyDown | KeyUp event;
all forms instances have to be accessible (one possibility is Application.OpenForms);
when hotkey is pressed, find next / previous window and make it active.
Can I know if there is anyway that I can maximise my windows form application from the system tray using say a Keyboard Shortcut rather than clicking on it?
I am currently minimizing using this piece of code
//Minimize to Tray with over-ride for short cut
private void MinimiseToTray(bool shortCutPressed)
{
notifyIcon.BalloonTipTitle = "Minimize to Tray App";
notifyIcon.BalloonTipText = "You have successfully minimized your app.";
if (FormWindowState.Minimized == this.WindowState || shortCutPressed)
{
notifyIcon.Visible = true;
notifyIcon.ShowBalloonTip(500);
this.Hide();
}
else if (FormWindowState.Normal == this.WindowState)
{
notifyIcon.Visible = false;
}
}
Hence, I need a keyboard shortcut that should maximize it. Much thanks!
EDIT: If you simply want to 'reserve a key combination' to perform something on your application, a Low-Level keyboard hook whereby you see every keypress going to any other application is not only an overkill, but bad practice and in my personal view likely to have people thinking that you're keylogging! Stick to a HOT-KEY!
Given that your icon will not have keyboard focus, you need to register a global keyboard hotkey.
Other similar questions:
How can I register a global hot key to say CTRL+SHIFT+(LETTER)
Best way to tackle global hotkey processing in c#?
Example from Global Hotkeys With .NET:
Hotkey hk = new Hotkey();
hk.KeyCode = Keys.1;
hk.Windows = true;
hk.Pressed += delegate { Console.WriteLine("Windows+1 pressed!"); };
if (!hk.GetCanRegister(myForm))
{
Console.WriteLine("Whoops, looks like attempts to register will fail " +
"or throw an exception, show error to user");
}
else
{
hk.Register(myForm);
}
// .. later, at some point
if (hk.Registered)
{
hk.Unregister();
}
To do this, you must use "Low-Level Hook".
You will find all information about it on this article : http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
Look at this too : http://www.codeproject.com/Articles/6362/Global-System-Hooks-in-NET
I second Franck's suggestion about a global keyboard hook. Personally, I had very good experiences with the CodeProject article "Processing Global Mouse and Keyboard Hooks in C#".
As they write in their article, you can do things like:
private UserActivityHook _actHook;
private void MainFormLoad(object sender, System.EventArgs e)
{
_actHook = new UserActivityHook();
_actHook.KeyPress += new KeyPressEventHandler(MyKeyPress);
}
You could then call a function in your MyKeyPress handler that opens your window.
If you follow the guide here. It will show you how to register a global shortcut key.
public partial class Form1 : Form
{
KeyboardHook hook = new KeyboardHook();
public Form1()
{
InitializeComponent();
// register the event that is fired after the key press.
hook.KeyPressed += new EventHandler<KeyPressedEventArgs>(hook_KeyPressed);
// register the CONTROL + ALT + F12 combination as hot key.
// You can change this.
hook.RegisterHotKey(ModifierKeys.Control | ModifierKeys.Alt, Keys.F12);
}
private void hook_KeyPressed(object sender, KeyPressedEventArgs e)
{
// Trigger your function
MinimiseToTray(true);
}
private void MinimiseToTray(bool shortCutPressed)
{
// ... Your code
}
}
how to notify my application when show desktop/minimize all/ all windows minimized using c#
The following might get you started. This is just a standard form with a ListBox on it (named listMessages). When I perform a desktop minimize/showall, the form catches the WM_SIZE messages and outputs the Message m values to the ListBox. Your form may not respond to typical minimize and maximize events but it should receive these messages from the windows message pump. As far as detecting if any another window has been shown that's a bit more involved but can be done as well....
using System;
using System.Windows.Forms;
namespace MinimizeAll
{
public partial class Form1 : Form
{
private const int WmSize = 5;
private const int SizeRestored = 0;
private const int SizeMinimized = 1;
private const int SizeMaximized = 2;
private const int SizeShow = 3;
private const int SizeHide = 4;
public Form1()
{
InitializeComponent();
}
protected override void WndProc(ref Message m)
{
try
{
if (m.Msg == WmSize)
{
var wparam = m.WParam.ToInt32();
switch (wparam)
{
case SizeRestored:
case SizeMinimized:
case SizeMaximized:
case SizeShow:
case SizeHide:
var output = string.Format("{0}{1:X} {2:X} {3:X} {4:X} {5:X}", prefix, m.Msg, m.WParam.ToInt32(), m.LParam.ToInt32(), m.HWnd.ToInt32(), m.Result.ToInt32());
listMessages.Items.Add(output);
break;
default:
// this is just a demo (code police)...
base.WndProc(ref m);
return;
}
}
else
{
base.WndProc(ref m);
}
}
catch (Exception)
{
listMessages.Items.Add("err");
base.WndProc(ref m);
}
}
}
}
I completely agree with Ian Boyd's comment. In no way should you try to circumvent defined system behavior. However, to abide by defined system behavior and still (maybe) get what you are looking for, you might want to look into using appbars for your main window which you do not want to have hidden. An appbar, is like the taskbar, it stays visible all of the time except when a fullscreen application is running.
Add Reference of Microsoft Shell Controls And Automation In COM
Use Namespace Shell32
Code:
Shell32.Shell s32 = new Shell32.Shell();
Call s32 object in your desired state..
So... in order to minimize all the windows you can use the following:
Add to your project the "Microsoft Shell Controls And Automation" COM reference(References=>Add=>COM).
then do the folowing:
Shell32.ShellClass shell = new Shell32.ShellClass();
shell.MinimizeAll(); // can also do: shell.UndoMinimizeAll();
or with the late binding:
Object shell;
shell = CreateObject("Shell.Application");
shell.MinimizeAll();
Now I am not sure if you can use some events of this COM (like AllMinimized)...
In order to prevent a WinForm application from minimizing(via Minimize button):
void Form1_Resize(object sender, System.EventArgs e) // Handles Form1.Resize
{
if (this.WindowState == FormWindowState.Minimized)
this.WindowState = FormWindowState.Normal;
}
You can also take a look here:
http://pinvoke.net/default.aspx/user32.EnumDesktopWindows
In order for you application to know when it is minimized (the most probable event for how desktop/minimize all/ all windows minimized, You need to check on the
this.WindowState
property of your application's current form. if it is minimized then it should be equal to
FormWindowState.Minimized
Edited:
try this out:
foreach (Process proc in Process.GetProcesses())
{
/// check proc.StartInfo.ProcessWindowStyle here
/// it Gets window state to use when the process is started.
}
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo_properties.aspx