Currently I have global hot keys setup to paste the contents of a text box into the current active form (browser). These work perfectly fine (CTRL + 0 - 9), however I'm trying to do a reverse of that by setting the text box value from an external value. Initially I thought it would be easy, since they're global hotkeys I'd just highlight what I want and then press the hotkey (ALT + 0 - 9) and it would SendKeys.Send("^c"), and then set the TextBox.Text = Clipboard.GetText(), however this doesn't behave as expected and returns seemingly random values from in my code/past clipboard entries.
I had a look around and found various things which also didn't help. It's important to note that I'll always be calling this global hotkey from the current active window, so I don't need to find/set the active window, meerly just send a ctrl + C command and have it reliably execute it.
Any help is appreciated, thanks.
RegisterHotKey(Handle, 12, 0x0001, (int) Keys.D1);
case (12):
if (x.Text == "" || x.Text == #"YYYYYY")
{
//Window is in Focus and the text is already highlighted
SendKeys.SendWait("^c");
x.Text = Clipboard.GetText();
}
return;
Bonus points, can I expand the clipboard class to return the count of the selection before doing anything?
Edit:
My attempt at Sending WM_COPY:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
case (12):
if (x.Text == "" || x.Text == #"YYYYYY")
{
//Window is in Focus and the text is already highlighted
SendMessage(m.HWnd, 0x0301, (IntPtr)0, (IntPtr)0);
x.Text = Clipboard.GetText();
}
return;
Related
How would I make my program check if a certain application like "notepad" has focus and ultimately open my second form when it does have focus, closing that second form when it loses focus.
(I would Also like to include an updater so that if the checkbox is checked while "notepad" is closed keep the checkbox checked, but do not open my second form until "notepad" has been opened) I know this is a very specific question and hence why I couldn't find anything relative to this.
Here is a mockup of what I believe it would look like:
DLL import
getforeground window
Process g = "notepad"
if (g is Foreground window in front && checkbox.checked) // my checkbox i use to enable the program
{
show form two
}
else
{
hide form two
}
My solution for anyone who wants to only make their code run when a specific program is open.
This is great for Mouse events + sending inputs when a specific program is opened. (Removes that craziness from happening when outside of that program)
FirstlyImport DLLs:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);
Second create this string to capture what window is active:
public 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;
}
Reminder if you wish to test which application you have open just maker a timer on 1 second repeat and type this inside the timer:
Console.Writeline(GetForegroundWindow());
Once you know your applications name (Also shows the name on taskbar - not task manager) You will want to type:
if (GetActiveWindowTitle() == "Notepad") // change notepad to your program
{
// do what you want to do
}
Hopefully this helps someone like it helped me :)
In a few words: blocking Win up after Win + Tab makes Windows think Win is still down, so then pressing S with the Win key up for example will open the search charm rather than just type "s"... until the user presses Win again. Not blocking it means the Windows Start menu will show up. I'm in a conundrum!
I have no trouble hooking into shortcuts using Alt + Tab using LowLevelKeyboardHook, or Win + Some Ubounded Key using RegisterHotKey. The problem happens only with the Win key using LowLevelKeyboardHook.
In the example below, I'm taking over the Win up event when the Win + Tab combination is detected. This results in making every following keystrokes behave as if the Win key was still down.
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode != HC_ACTION)
return CallNextHookEx(_hookID, nCode, wParam, lParam);
var keyInfo = (Kbdllhookstruct)Marshal.PtrToStructure(lParam, typeof(Kbdllhookstruct));
if (keyInfo.VkCode == VK_LWIN)
{
if (wParam == (IntPtr)WM_KEYDOWN) {
_isWinDown = true;
} else {
_isWinDown = false;
if (_isWinTabDetected) {
_isWinTabDetected = false;
return (IntPtr)1;
}
}
}
else if (keyInfo.VkCode == VK_TAB && _isWinDown) {
_isWinTabDetected = true;
if (wParam == (IntPtr)WM_KEYDOWN) {
return (IntPtr)1;
} else {
_isWinTabDetected = true;
Console.WriteLine("WIN + TAB Pressed");
return (IntPtr)1;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
}
}
You can find the complete code here (note that it should replace your Program.cs in an empty WinForms project to run): https://gist.github.com/christianrondeau/bdd03a3dc32a7a718d62 - press Win + Tab and the Form title should update each time the shortcut is pressed.
Note that the intent of hooking into this specific combination is to provide an Alt + Tab alternative without replacing Alt + Tab itself. An answer providing the ability to launching custom code using Win + Tab will also be accepted.
Here are my ideas, for which I could not find documentation. All would potentially answer my question successfully.
Tell Windows to "cancel" the Win up without actually triggering it
Prevent Windows from launching the Start menu once
Hook directly in the Windows' Win + event rather than manually hooking into the keystrokes (This would be by far my first choice if that exists)
System need to know you release the Windows key.
I check the difference between my own hook who doesn't have this problem and the only diffence between your and mine is this line :
if (_isWinTabDetected) {
_isWinTabDetected = false;
return (IntPtr)1; //THIS LINE
}
This appears to do exactly what you want (omit RWin if you wish).
Please be considerate and unregister this KB hook when your app loses focus!
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(System.Windows.Forms.Keys vKey);
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode == HC_ACTION)
{
var keyInfo = (Kbdllhookstruct) Marshal.PtrToStructure(lParam, typeof (Kbdllhookstruct));
if ((int) wParam == WM_KEYDOWN
&& keyInfo.VkCode == VK_TAB
&& (GetAsyncKeyState(Keys.LWin) < 0 || GetAsyncKeyState(Keys.RWin) < 0))
{
_mainForm.Text = "Win + Tab was pressed " + (++_winTabPressCounter) + " times";
return (IntPtr) 1;
}
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
I tried several things before discovering this technique.
This post was the most helpful https://stackoverflow.com/a/317550/55721
I am in the process of integrating support for USB barcode scanners into a WPF application, but I have hit a snag.
Currently I am successfully identifying and capturing input with the help of this article.
The issue that I am facing is that although I am successfully identifying and routing input from the scanner device, I am unable to block the input events for further processing (e.g. if a textbox control on my application has input focus, the input from the scanner will be written to it).
I have tried two methods of capturing input:
var wndSourceHandle = HwndSource.FromHwnd(new WindowInteropHelper(
_wndEventSource = value).Handle);
wndSourceHandle.AddHook(this.WndProc);
WndProc definition:
private IntPtr WndProc(IntPtr hwnd, int iMessage, IntPtr wParam, IntPtr lParam, ref bool bisHandled)
{
if (iMessage == Win32.WM_INPUT)
{
var result = ProcessRawInput(lParam);
bisHandled = result != null && result.Value;
return IntPtr.Zero;
}
return IntPtr.Zero;
}
As well as:
ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) =>
{
if (msg.message == Win32.WM_INPUT)
{
var result = ProcessRawInput(msg.lParam);
handled = result != null && result.Value;
return;
}
handled = false;
};
The ProcessRawInput method returns true if the source of the input is the barcode scanner, false otherwise.
After a bit more research I found a solution applicable to WinForms here. I was able to modify it for WPF as follows:
ComponentDispatcher.ThreadFilterMessage += (ref MSG msg, ref bool handled) =>
{
if (msg.message == Win32.WM_INPUT)
{
var result = ProcessRawInput(msg.lParam);
this.m_bIgnoreNextKeyDownMessage = result != null && result.Value;
return;
}
if (msg.message == Win32.WM_KEYDOWN && this.m_bIgnoreNextKeyDownMessage)
{
handled = true;
}
this.m_bIgnoreNextKeyDownMessage = false;
};
This solution basically marks the first WM_KEYDOWN message after a barcode WM_INPUT message as "handled". I am not sure if this is the only/best/safest solution, but it looks like it does the trick.
Update:
With the above solution I still found that every now and again one random character from the scanned barcode would slip through to a focussed textbox - I am not sure why this is the case - could be a timing issue with the keyboard events as they are passed through the message handler. Another solution for checking whether the WM_KEYDOWN message should be ignored:
if (msg.message == Win32.WM_KEYDOWN && !String.IsNullOrEmpty(this.m_strKeyInput))
{
handled = true;
}
The buffer m_strKeyInput contains the current scanned barcode value - this buffer is empty when no barcode is available, built up one character at a time as the barcode scanner pushes down the barcode - and then emptied once a custom BarcodeScanned event is generated. The only drawback of this solution that I can think of is that all keyboards will stop functioning for the few milliseconds the barcode is being pushed from the scanner - which is acceptable for my scenario.
It sounds like since you are routing the input from the scanner (treating it as a keyboard) and into a textbox you could simply use one of the Preview* events on that textbox to perform your additional processing. For example you could override PreviewTextInput
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
// MyBarcodeScanner would be a reference to the IInput device that represents the scanner:
if (e.Device == MyBarcodeScanner)
{
// Process the text, rejecting it in this case.
// Marking the event as handled will prevent the 'TextChanged' event
// from firing, so the characters will not appear in the text box.
e.Handled = true;
}
else
{
// This is some other keyboard, by not handling the event,
// the users will be allowed to enter text normally.
}
}
You may have to do a little trial and error to figure out how to identify the barcode scanner that is identified by 'e.Device' but that should be relatively easy. Sorry I can't be more complete, but I don't have a barcode scanner of my own to experiment with.
For my subclassed RichTextBox class, I can capture, suppress the default behaviour of and re-purpose Ctrl+Shift+#, as long as # is between 1 and 9. For Ctrl+Shift+0, I can't. I have experimented with ProcessCmdKey in the form class and onKeyDown and PreProcessMessage in the control class.
Here is sample code meant for the control class that should suppress Ctrl+Shift+0 but does not:
public override bool PreProcessMessage(ref Message msg)
{
bool cancel = false;
int vKeyCode = (int)msg.WParam;
if(msg.Msg == WinApi.WM_KEYDOWN)
{
bool ctrlDown = (WinApi.GetKeyState(Keys.ControlKey) & (1 << 16)) == (1 << 16);
bool altDown = (WinApi.GetKeyState(Keys.Alt) & (1 << 16)) == (1 << 16);
bool shiftDown = (WinApi.GetKeyState(Keys.ShiftKey) & (1 << 16)) == (1 << 16);
if(ctrlDown && shiftDown && vKeyCode == (int)Keys.D0)
{
Debug.WriteLine("Cancel!");
cancel = true;
}
}
return cancel ? true : base.PreProcessMessage(ref msg);
}
However, changing Keys.D0 to Keys.D1 shows that the sample otherwise works.
If it's a clue, the default behaviour of the RichTextBox, in response to Ctrl+Shift+0, is to change the font. I went hunting for documentation that mentions this as a built-in shortcut but I didn't find anything (maybe I'm not using the correct search terms).
How should I detect Ctrl+Shift+0 so that I can suppress the default behaviour and write my own?
After some tries, I've found out how to actually suppress the Ctrl + Shift + D0. However the new problem was even tougher, the Ctrl + Shift + D0 was suppressed OK but the beep sound was generated when releasing the Ctrl and Shift, that's so annoying because you said you wanted to override these keys combination not discard it. So the beep sound should not be generated.
After searching much with a hope there was some style to apply to RichTextBox to prevent the beep sound or some message to discard resulting in suppressing the beep sound but there are not any such things. I were almost disappointed and intended to let your question unanswered forever. I didn't want to add the answer which just partially solved your problem. However it was luckily that I tried sending some key instead of the discarded 0 key to consume the keys combination and make the keys combination valid so no beep sound would be generated. Here is the entire code for you, note that we have to use some global low-level keyboard hook here, as I said the Application-level message filter also couldn't help:
[DllImport("user32")]
private static extern IntPtr SetWindowsHookEx(int hookType, KeyboardLowLevelProc proc, IntPtr moduleHandle, int threadID);
[DllImport("user32")]
private static extern int UnhookWindowsHookEx(IntPtr hHook);
[DllImport("user32")]
private static extern IntPtr CallNextHookEx(IntPtr hHook, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32")]
private static extern IntPtr GetModuleHandle(string moduleName);
public struct KBDLLHOOKSTRUCT
{
public Keys key;
public int scanCode;
public int flags;
public int time;
public IntPtr extra;
}
public delegate IntPtr KeyboardLowLevelProc(int hCode, IntPtr wParam, IntPtr lParam);
public IntPtr KeyboardLowLevelCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0) {
KBDLLHOOKSTRUCT kbd = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(KBDLLHOOKSTRUCT));
if (kbd.key == Keys.D0 && blockD0) {
if(ModifierKeys == (Keys.Control | Keys.Shift)) {
SendKeys.Send("{ESC}");
//Add custom code as the response to Ctrl + Shift + D0 here
//....
}
return new IntPtr(1);//Discard the default behavior
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
bool blockD0;
KeyboardLowLevelProc proc; //this should be declared in the form scope
IntPtr hHook;
//your Form1 constructor
public Form1(){
InitializeComponent();
//Get current module Handle
IntPtr currentModuleHandle = GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName);
//Set the keyboard hook
hHook = SetWindowsHookEx(13, proc, currentModuleHandle, 0);//WH_KEYBOARD_LL = 13
//register these Key events for your richTextBox1
richTextBox1.KeyDown += (s, e) => {
if(e.KeyCode != Keys.D0) blockD0 = true;
};
richTextBox1.KeyUp += (s, e) => {
if (ModifierKeys == Keys.None) blockD0 = false;
};
//Unhook keyboard when form is closed
FormClosed += (s,e) => {
if (hHook != IntPtr.Zero) {
UnhookWindowsHookEx(hHook);
hHook = IntPtr.Zero;
}
}
}
A little about the explanation: I do not understand exactly why we have to use Global Low-level Keyboard hook here, I guess that when the keys combination Ctrl + Shift + D0 is pressed, there may be some key message cloned and dispatched to another thread, that's why all the manual interceptions in the current thread can't intercept or override the Ctrl + Shift + D0, however the global low-level keyboard hook can handle the key messages in all threads of the current module and it can intercept any key messages.
I mentioned about the beep sound problem, if you want to experience it, just remove the SendKeys.Send("{ESC}");, in fact you can try some other keys like 1, 2, ... they also make the keys combination Ctrl + Shift + ... valid and help avoid any beep sound.
UPDATE
The solution above works OK, it's the best solution with the point that the Ctrl + Shift + D0 should be discarded cleanly and totally. However it's a little long (as you can see). I've found that when you press the Ctrl + Shift + D0, the message WM_INPUTLANGCHANGEREQUEST is sent, this message causes the behavior which you don't want. So we can try another solution, with PreProcessMessage you can still catch the combination Ctrl + Shift + D0 but you just can't discard it (because it's dispatched to another thread), that means you can add your own code there, instead of discarding the Ctrl + Shift + D0, we can discard the effect/behavior it causes instead by discarding the message WM_INPUTLANGCHANGEREQUEST. We have the following code:
//Create a custom RichTextBox class
public class CustomRichTextBox : RichTextBox {
protected override void WndProc(ref Message m){
if(m.Msg == 0x50) return; //WM_INPUTLANGCHANGEREQUEST = 0x50
base.WndProc(ref m);
}
public override bool PreProcessMessage(ref Message msg) {
if (msg.Msg == 0x100)//WM_KEYDOWN = 0x100
{
Keys keyData = (Keys)msg.WParam | ModifierKeys;
if(keyData == (Keys.Control | Keys.Shift | Keys.D0)){
//your own code goes here...
}
}
return base.PreProcessMessage(ref msg);
}
}
You can see that the second approach is much shorter, however as I said, it doesn't actually suppress the Ctrl + Shift + D0, it just suppresses the default behavior caused by the message WM_INPUTLANGCHANGEREQUEST. I guess it's enough to solve your problem.
I have been trying to send mouse clicks to a WebBrowser control inside of my form using PostMessage(), and I have run into a rather significant issue. What I am trying to achieve is to simulate mouse clicks on this WebBrowser while my form is minimized. Usually PostMessage() would work just fine doing this, but it seems that it only works while my form has focus. This leads me to believe that there is some check going on to see if the particular website I am loading into my WebBrowser control is in focus before it handles mouse events.
This is how I send the clicks with my program:
private void SendClick(Point location)
{
resetHandle = true;
StringBuilder className = new StringBuilder(100);
while (className.ToString() != "Internet Explorer_Server")
{
handle = GetWindow(handle, 5); // 5 == child
GetClassName(handle, className, className.Capacity);
//MessageBox.Show(className.ToString());
}
IntPtr lParam = (IntPtr)((location.Y << 16) | location.X);
IntPtr wParam = IntPtr.Zero;
const uint downCode = 0x201;
const uint upCode = 0x202;
const uint moveCode = 0x200;
PostMessage(handle, moveCode, wParam, lParam); //move mouse
PostMessage(handle, downCode, wParam, lParam); // mousedown
PostMessage(handle, upCode, wParam, lParam); // mouseup
}
This is what the resetHandle does:
private void timer3_Tick(object sender, EventArgs e)
{
if (resetHandle == true)
{
handle = webBrowser1.Handle;
resetHandle = false;
}
}
I'm not sure if there is a better way of sending mouse events to a background window and I am open to any ideas. What I am really asking though is if it is at all possible to make a window believe it is in focus when it is actually still minimized?
Any help at all would be much appreciated!
Rather than keep the window minimized, keep it normal (restored), but set its X or Y coordinate so that it is positioned off screen.
If you want give the user the illusion of minimizing and restoring it, use HwndSource.AddHook to watch for SC_MINIMIZE. In your HwndSourceHook handler, move the window on or off screen according to the pseudo-minimized state, and set handled to true.