I have maui app with blazor I removed the windows default title bar, I'm creating a custom one with blazor
The code works fine, but the mouse is stuck at the point where it was clicked, it is in the busy state
The application moves normally, but the window is stuck to the mouse.
The code is:
Blazor:
<div class="bg-default w-full h-3 fixed" #onmousedown="#MoveWindow">
....
</div>
#code {
[DllImport("user32.dll")]
static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, UIntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
static extern bool ReleaseCapture();
const uint WM_SYSCOMMAND = 0x112;
const uint MOUSE_MOVE = 0xF012;
private void MoveWindow()
{
var win = App.Current.Windows.First();
var view = win.Handler.PlatformView;
IntPtr Handle = WinRT.Interop.WindowNative.GetWindowHandle(view);
ReleaseCapture();
DefWindowProc(Handle, WM_SYSCOMMAND, (UIntPtr)MOUSE_MOVE, IntPtr.Zero);
}
}
Does anyone know how I can remove mouse stuck in busy state?
Is there another way to move the maui window other than the code I used?
Related
I want to simulate F5 key press in my C# program. When IE is open, I want to be able refresh my website automatically.
How can I do that?
Here's an example...
static class Program
{
[DllImport("user32.dll")]
public static extern int SetForegroundWindow(IntPtr hWnd);
[STAThread]
static void Main()
{
while(true)
{
Process [] processes = Process.GetProcessesByName("iexplore");
foreach(Process proc in processes)
{
SetForegroundWindow(proc.MainWindowHandle);
SendKeys.SendWait("{F5}");
}
Thread.Sleep(5000);
}
}
}
a better one... less anoying...
static class Program
{
const UInt32 WM_KEYDOWN = 0x0100;
const int VK_F5 = 0x74;
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
[STAThread]
static void Main()
{
while(true)
{
Process [] processes = Process.GetProcessesByName("iexplore");
foreach(Process proc in processes)
PostMessage(proc.MainWindowHandle, WM_KEYDOWN, VK_F5, 0);
Thread.Sleep(5000);
}
}
}
You can use the Win32 API FindWindow or FindWindowEx to find the window handle of the open browser and then just call SendMessage with WM_KEYDOWN. Typically it's easiest just to pass the window caption to FindWindowEx and have it find the associated window handle for you.
If you are starting the browser process yourself via a Process process object then you can use process.MainWindowHandle instead of calling FindWindowEx.
Spy++ is a very useful tool when you want to start working with other windows. It basically allows you to learn another program's hierarchy of UI elements. You can also monitor all of the messages that go into the window you're monitoring. I have more info in this thread.
The F5 keystroke has this virtual key code:
const int VK_F5 = 0x74;
The p/invoke signature for FindWindowEx in C# is:
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
You can p/invoke (bring in) the Win32 API SendMessage like this:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
So to recap, you call FindWindowEx directly from your C# code after having the above code somewhere inside your class. FindWindowEx will return a window handle. Then once you have the window handle, you can send any keystroke(s) to the window, or call many other Win32 API calls on the window handle. Or even find a child window by using another call to FindWindowEx. For example you could select the edit control of the browser even and then change it's text.
If all else goes wrong and you think you're sending the right key to the window, you can use spy++ to see what messages are sent to the window when you manually set focus to the browser and manually press F5.
The easiest way to send (simulate) KeyStrokes to any window is to use the SendKeys.Send method of .NET Framework.
Checkout this very intuitive MSDN article http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.aspx
Particularly for your case, if your browser window is in focus, sending F5 would just involve the following line of code:
SendKeys.Send("{F5}");
Simple one, add before Main
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);
Code inside Main/Method:
string className = "IEFrame";
string windowName = "New Tab - Windows Internet Explorer";
IntPtr IE = FindWindow(className, windowName);
if (IE == IntPtr.Zero)
{
return;
}
SetForegroundWindow(IE);
InputSimulator.SimulateKeyPress(VirtualKeyCode.F5);
Note:
Add InputSimulator as reference. To download Click here
To find Class & Window name, use WinSpy++. To download Click here
Another alternative to simulating a F5 key press would be to simply host the WebBrowser control in the Window Forms application. You use the WebBrowser.Navigate method to load your web page and then use a standard Timer and on each tick of the timer you just re-Navigate to the url which will reload the page.
Easy, short and no need window focus:
Also here a usefull list of Virtual Key Codes
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam);
private void button1_Click(object sender, EventArgs e)
{
const int WM_SYSKEYDOWN = 0x0104;
const int VK_F5 = 0x74;
IntPtr WindowToFind = FindWindow(null, "Google - Mozilla Firefox");
PostMessage(WindowToFind, WM_SYSKEYDOWN, VK_F5, 0);
}
Use mouse_event or keybd_event. They say not to use them anymore but you don't have to find the window at all.
using System;
using System.Runtime.InteropServices;
public class SimulatePCControl
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void keybd_event(uint bVk, uint bScan, uint dwFlags, uint dwExtraInfo);
private const int VK_LEFT = 0x25;
public static void LeftArrow()
{
keybd_event(VK_LEFT, 0, 0, 0);
}
}
Virtual Key Codes are here for this one: http://www.kbdedit.com/manual/low_level_vk_list.html
Also for mouse:
using System.Runtime.InteropServices;
using UnityEngine;
public class SimulateMouseClick
{
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo);
//Mouse actions
private const int MOUSEEVENTF_LEFTDOWN = 0x02;
private const int MOUSEEVENTF_LEFTUP = 0x04;
private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
private const int MOUSEEVENTF_RIGHTUP = 0x10;
public static void Click()
{
//Call the imported function with the cursor's current position
uint X = (uint)0;
uint Y = (uint)0;
mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, 0);
Debug.LogError("SIMULATED A MOUSE CLICK JUST NOW...");
}
//...other code needed for the application
}
Instead of forcing an F5 keypress when you're just trying to get the page to postback, you can call a postback based on a JS event (even mousemove or timer_tick if you want it to fire all the time). Use the code at http://weblogs.asp.net/mnolton/archive/2003/06/04/8260.aspx as a reference.
what I want to do is to extend the MainMenu of the Windows Mobile Winforms to have a second menu level. If you tip short on the menu button it will do the event action but if you press it longer a second menu level should pop up. The MainMenu is very deficient in its managed functions so I had to find another way. I archived this by deriving MainMenu and add some SubClassing.
public delegate IntPtr Win32WndProc(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("coredll.dll", EntryPoint = "FindWindow", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, IntPtr lpWindowName);
[DllImport("coredll.dll")]
public static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
[DllImport("coredll")]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, Win32WndProc newProc);
int GWL_WNDPROC = (-4);
int GW_CHILD = 5;
IntPtr _oldToolbarProc;
IntPtr _oldMenuWorkerProc
void Hookup()
{
//find the window to hook
var hWndHooked = FindWindow("HHTaskbar", IntPtr.Zero);
if (hWndHooked == IntPtr.Zero)
return;
//enable the taskbar, not realy necessary
EnableWindow(hWndHooked, true);
//find the menu_worker window
var menuWorkerWnd = FindWindow("menu_worker", IntPtr.Zero);
if (menuWorkerWnd == IntPtr.Zero)
return;
var toolbarWnd = GetWindow(menuWorkerWnd, GW_CHILD);
if (toolbarWnd == IntPtr.Zero)
return;
Win32WndProc newMenuWorker = MenuWorkerProc;
_oldMenuWorkerProc = SetWindowLong(menuWorkerWnd, GWL_WNDPROC, newMenuWorker);
Win32WndProc newToolbar = ToolbarProc;
_oldToolbarProc = SetWindowLong(newToolbarWnd, GWL_WNDPROC, newToolbar);
}
The toolbar subclassing measures the time between WM_LBUTTONDOWN and WM_LBUTTONUP
and depending on the time leaped between these events a context Menu is invoked.
If the context menu is invoked the menu_worker subclassing must suppress the WM_COMMAND of the pressed button.
This works fine for a single window. But if I use it on a second form they will recongize both the same toolbar and menuworker and application crashes.
What I tried is to hook and unhook in the onFocus /onLostFocus events of the parent form.
But sadly onFocus is called before the right window is visible and it also gets the wrong window handle :(
What I did now (I know a very bad hack) is to start a time in the onFocus event and wait for 1000ms and hook it up then. This results in a 50:50 change to hook the right window..
Isn't there a better solution for subclassing the right window?
I have an application named ProLaunch.exe. I want to get the active window in it and close it if the user is not performing any operation for the speicified period. A timer in the application will be used for this purpose.
How can I get the active window and close it?
If I understand the question correctly, you can use the Win32 API GetActiveWindow for this. This should work in both Forms and WPF apps.
[DllImport("user32.dll")]
static extern IntPtr GetActiveWindow();
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, IntPtr msg, int wParam, int lParam);
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_CLOSE = 0xF060;
// close the active window using API
private void FindAndCloseActiveWindow()
{
IntPtr handle=GetActiveWindow();
SendMessage(handle, WM_SYSCOMMAND, SC_CLOSE, 0);
}
Try
Form.ActiveForm
http://msdn.microsoft.com/de-de/library/system.windows.forms.form.activeform.aspx
I'm trying to set with c# a process window to the foreground / focus (from an application that has no focus in that moment when doing it), therefore I'm using the user32.dll static extern bool SetForegroundWindow(IntPtr hWnd) method:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
public void setFocus()
{
SetForegroundWindow(process.MainWindowHandle);
}
Every thing is working fine, but only if I have the visual studio 2008 open, I don't even need to to start the application from the VS08, it's enough to have the project open with it. The moment I'm closing the project my application can't set the other window to the foreground. The only result is that in the taskbar the other window is blue highlighted. The moment I'm going to open my project with the VS08 again it's working fine.
I have not the slightest idea why...I thought the problem could be that he can't import the dll but then it wouldn't be highlighted, and other win32 functions like static extern bool ShowWindow(IntPtr hWnd, IntPtr status); are working even when the project is closed.
Any solutions or hints for this problem?
Edit:
I read the remarks for the function and I had the idea that my application has not the focus, so I tried this one:
[DllImport("user32.dll")]
static extern bool SetForegroundWindow(IntPtr hWnd);
[return: MarshalAs(UnmanagedType.Bool)]
[DllImport("user32.dll")]
static extern bool AllowSetForegroundWindow(int procID);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
public void setAUTFocus()
{
IntPtr hWnd = GetForegroundWindow();
uint processID = 0;
uint threadID = GetWindowThreadProcessId(hWnd, out processID);
int intID = (int)processID;
AllowSetForegroundWindow(intID);
SetForegroundWindow(process.MainWindowHandle);
}
Now I'm searching for the window process that has focus at the moment and set the AllowSetForegroundWindow for this window and trying to set the focus on my window now. But the same problem, the moment I have the project in VS open it's working, if not I'm getting only the blue highlight in the taskbar.
During having my application running I can open / close the vs project, the moment it's open everything is working, the moment it's closed it's not working, I have no interaction with the VS project while running my application. Seriously I don't get it.
After searching a few days on the internet I have found one posible simple solution to make SetForegroundWindow to work on windows 7: press Alt key before calling SetForegroundWindow.
public static void ActivateWindow(IntPtr mainWindowHandle)
{
//check if already has focus
if (mainWindowHandle == GetForegroundWindow()) return;
//check if window is minimized
if (IsIconic(mainWindowHandle))
{
ShowWindow(mainWindowHandle, Restore);
}
// Simulate a key press
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | 0, 0);
//SetForegroundWindow(mainWindowHandle);
// Simulate a key release
keybd_event((byte)ALT, 0x45, EXTENDEDKEY | KEYUP, 0);
SetForegroundWindow(mainWindowHandle);
}
And the win32api imports
private const int ALT = 0xA4;
private const int EXTENDEDKEY = 0x1;
private const int KEYUP = 0x2;
private const uint Restore = 9;
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern int ShowWindow(IntPtr hWnd, uint Msg);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
I had an issue with sending the Alt-key as it forced the window menu to open when I selected enter (instead of the OK button which is what I wanted).
This worked for me:
public static void ActivateWindow(IntPtr mainWindowHandle)
{
//check if already has focus
if (mainWindowHandle == GetForegroundWindow()) return;
//check if window is minimized
if (IsIconic(mainWindowHandle))
{
ShowWindow(mainWindowHandle, Restore);
}
// Simulate a key press
keybd_event(0, 0, 0, 0);
SetForegroundWindow(mainWindowHandle);
}
i am trying to grab the selected text from the open form on a users machine. Currently i have tried using GetFocus which is defined as
'[DllImport("user32.dll")]
static extern int GetFocus();'
In the api it says - Retrieves the handle to the window that has the keyboard focus, if the window is attached to the calling thread's message queue. Which explains why my app can grab the selected text from a window thats part of my app, but not one thats external, like a pdf for example.
What alternative win32 method is available for me to use that would fit this purpose?
Thanks.
edit: this is the attempt at the moment
[DllImport("user32.dll")]
static extern int GetFocus();
[DllImport("user32.dll")]
static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(int hWnd, int ProcessId);
[DllImport("user32.dll")]
static extern int GetForegroundWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern int SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);
// second overload of SendMessage
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);
const int WM_SETTEXT = 12;
const int WM_GETTEXT = 13;
private static string PerformCopy()
{
try
{
//Wait 5 seconds to give us a chance to give focus to some edit window,
//notepad for example
System.Threading.Thread.Sleep(1000);
StringBuilder builder = new StringBuilder(500);
int foregroundWindowHandle = GetForegroundWindow();
uint remoteThreadId = GetWindowThreadProcessId(foregroundWindowHandle, 0);
uint currentThreadId = GetCurrentThreadId();
//AttachTrheadInput is needed so we can get the handle of a focused window in another app
AttachThreadInput(remoteThreadId, currentThreadId, true);
//Get the handle of a focused window
int focused = GetFocus();
//Now detach since we got the focused handle
AttachThreadInput(remoteThreadId, currentThreadId, false);
//Get the text from the active window into the stringbuilder
SendMessage(focused, WM_GETTEXT, builder.Capacity, builder);
return builder.ToString();
}
catch (System.Exception oException)
{
throw oException;
}
}
Check GetForegroundWindow.
I don't think you have much chance of succeeding with your current approach. I'm pretty sure there's no single general purpose API for getting hold of the current selection. I believe this because each application can implement text selection in its own way.
As an alternative solution you should consider using a clipboard listener. Listen for changes to the clipboard contents and whenever text is added you can suck it out of the clipboard and put it in your app's window.
I think this is a job for UI Automation (the API screen readers use). Here's a post that get's the selected text in C#.