On every windows app there is that context menu that you can access with CTRL+Space bar:
I believe this menu is called the "Window Control Menu", but I am not sure.
It has the following options:
Restore
Move
Size
Minimize
Maximize
Close Alt+F4
Here is a pic:
How can I call this using win forms? My goal is to provide a keyboard shortcut to this menu by hitting alt+spacebar
Thanks.
Send a message to your own window so that the system menu appears.
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, int lParam);
private void callSysMenu()
{
int point = ((this.Location.Y << 16) | ((this.Location.X) & 0xffff));
SendMessage(this.Handle, 0x313, IntPtr.Zero, point);
}
Related
I have a Web Browser in my WPF application which plays a Flash, but the Flash has audio and I don't want the users to hear it. I'm assuming that there has to be some way to mute either the Web Browser, the Window or the entire Application. I've tried stuff like the following, but nothing has worked. Could I get some assistance, please?
private const int APPCOMMAND_VOLUME_MUTE = 0x80000;
private const int WM_APPCOMMAND = 0x319;
[DllImport("user32.dll")]
public static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam,
IntPtr lParam);
public EditTags() {
IntPtr windowHandle = new WindowInteropHelper(this).Handle;
SendMessageW(windowHandle, WM_APPCOMMAND, windowHandle, (IntPtr)
APPCOMMAND_VOLUME_MUTE);
}
EDIT:
A solution has been found by Jimi.
Link for those who want it: Webbrowser disable all audio output - from online radio to youtube.
I've imported:
public static extern IntPtr SetParent(
IntPtr hWndChild, // handle to window
IntPtr hWndNewParent // new parent window
);
from user32.dll in my windows forms application and continuously setting SetParent(hwndf,hwndParent); (if a variable is true) in a background thread.
Where
IntPtr hwndf = Control.Handle;
IntPtr hwndParent = FindWindow("ProgMan", null);
My question How do i reset the parent handle to be the default windows form handle, aka, how do I not display the window on top of the desktop window anymore? and is following, Is this an efficient way of doing this (repeatedly?).
Never mind. I could just use
SetParent(hwndf, new IntPtr(0));
When I wanted to "reset" the form window parent. The only problem was the the window was minimized, so my solution was running ShowWindow(hwndf, SW_RESTORE); after importing these methods from user32.dll!
[DllImport("user32.dll")]
public static extern IntPtr ShowWindow(
IntPtr hWnd, // handle to window
uint nCmdShow
);
private const uint SW_RESTORE = 0x09;
Well, first off, what I'm trying to do is click a specific point inside a flash object, inside of a webbrowser control. I'm not sure why it isn't working, but I cannot seem to click any window, be it notepad, or the actual program.
Here is my code that I'm using.
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string className, IntPtr windowTitle);
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(String sClassName, String sAppName);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll", SetLastError = true)]
static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);
public IntPtr find()
{
return this.Handle;//FindWindow("", "Form1");
}
public enum WMessages : int
{
WM_LBUTTONDOWN = 0x201, //Left mousebutton down
WM_LBUTTONUP = 0x202, //Left mousebutton up
WM_LBUTTONDBLCLK = 0x203, //Left mousebutton doubleclick
WM_RBUTTONDOWN = 0x204, //Right mousebutton down
WM_RBUTTONUP = 0x205, //Right mousebutton up
WM_RBUTTONDBLCLK = 0x206, //Right mousebutton do
}
private int MAKELPARAM(int p, int p_2)
{
return ((p_2 << 16) | (p & 0xFFFF));
}
/** This is the non-working code **/
public void DoMouseLeftClick(IntPtr handle, Point x)
{
SendMessage(handle, (int)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
SendMessage(handle, (int)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
return;
//I have tried PostMessage, and SendMessage, and both of them at the same time, and neither works.
PostMessage(handle, (uint)WMessages.WM_LBUTTONDOWN, 0, MAKELPARAM(x.X, x.Y));
PostMessage(handle, (uint)WMessages.WM_LBUTTONUP, 0, MAKELPARAM(x.X, x.Y));
}
private void timer2_Tick(object sender, EventArgs e)
{
//I try hovering my mouse over a button I added to the form, and nothing happens.
DoMouseLeftClick(find(), Cursor.Position);
}
So, I have tried using PostMessage, and SendMessage, and neither of those seem to work.
All I need it to do is to click on a specific point.
Also, I need to mention that I can't use mouse_event, because from what I know, the window needs to be active, plus the cursor needs to be over the point you are clicking. I am making a bot that automatically does a process in a flash object, so that's why I can't use mouse_event.
Thanks for your help guys.
I had the same problem.
I tried to draw something in the MS Paint. It turned out that I was clicking on the main window but it turned out that MS Paint (and most of the applications) consist of many child windows and you actually want to click on the child. So I had to change my code from:
IntPtr handle = FindWindow(null, "Untitled - Paint");
PostMessage(handle, (uint)MOUSE_BUTTONS.LEFT_DOWN, 0, lparam);
to
IntPtr handle = FindWindow(null, "Untitled - Paint");
handle = FindWindowEx(handle, IntPtr.Zero, "MSPaintView", null);
canvasHandle = FindWindowEx(handle, IntPtr.Zero, "Afx:00007FF676DD0000:8", null);
PostMessage(canvasHandle, (uint)MOUSE_BUTTONS.LEFT_DOWN, 0, lparam);
You need to use tools like Spy++ for Windows that comes with C++ Visual Studio package if you want to debug these kind of things (even if you program in C#)
Hope it helps someone.
For the WM_LBUTTONDOWN, you may need to specify which button. Take reference for: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645607(v=vs.85).aspx
I used:
SendMessage(hWnd, (int)WMessages.WM_RBUTTONDOWN, (int)KeyDownMessage.MK_LBUTTON, MAKELPARAM(x, y));
I want to detect whether another process say process.exe is currently displaying a dialog box ?
Is there a way to do that in C# ?
To see if I could get the handle of the dialog box. I have tried Spy++ 's find window tool, when I try to drag the finder on top of the dialog box, it does not highlight the dialogbox but populates the details and
mentions AppCustomDialogBox and mentions the handle number
Please advise how can I programatically detect that ..
Thanks,
When an application shows a dialog box, the (for me quietly annoying) behaviour of Windows Operating System is to show the newly created window on top of all other. So if I assume that You know which process to watch, a way to detect a new window is to set up a windows hook:
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
[DllImport("user32.dll")]
public static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
[DllImport("user32.dll")]
public static extern bool UnhookWinEvent(IntPtr hWinEventHook);
// Constants from winuser.h
public const uint EVENT_SYSTEM_FOREGROUND = 3;
public const uint WINEVENT_OUTOFCONTEXT = 0;
//The GetForegroundWindow function returns a handle to the foreground window.
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
// For example, in Main() function
// Listen for foreground window changes across all processes/threads on current desktop
IntPtr hhook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero,
new WinEventDelegate(WinEventProc), 0, 0, WINEVENT_OUTOFCONTEXT);
void WinEventProc(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
IntPtr foregroundWinHandle = GetForegroundWindow();
//Do something (f.e check if that is the needed window)
}
//When you Close Your application, remove the hook:
UnhookWinEvent(hhook);
I did not try that code explicitely for dialog boxes, but for separate processes it works well. Please remember that that code cannot work in a windows service or a console application as it requires a message pump (Windows applications have that). You'll have to create an own.
Hope this helps
As modal dialogs normally disable the parent window(s), you can enumerate all top level windows for a process and see if they're enabled using the IsWindowEnabled() function.
How to read the highlighted/Selected Text from any window using c#.
i tried 2 approaches.
Send "^c" whenever user selects some thing. But in this case my clipboard is flooded with lots of unnecessary data. Sometime it copied passwords also.
so i switched my approach to 2nd method, send message method.
see this sample code
[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 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(5000);
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;
}
}
this code working fine in Notepad. But if i try to capture from another applications like Mozilla firefox, or Visual Studio IDE, it's not returning the text.
Can anybody please help me, where i am doing wrong? First of all, i have chosen the right approach?
That's because both Firefox and Visual Studio don't use the built-in Win32 controls for displaying/editing text.
It is not possible in general to be able to get the value of "any" selected text, because of the fact that programs can re-implement their own version of the Win32 controls any way they see fit, and your program cannot possibly expect to work with all of them.
However, you can use the UI Automation APIs which will allow you to interact with the majority of 3rd-party controls (at least, all the good ones - such as Visual Studio and Firefox - will likely work with the UI Automation APIs since it's a requirement for accessibility)