I have a program which monitors user's presence by monitoring the mouse movements. I need to make that program think that a user is present at all times. Programmatically moving the mouse every once in a while is very simple. However, I can't make this work when the computer is locked.
I work on Windows XP and have no need for the solution to support Vista or 7.
I had a similar issue. Simulating a mouse click instead worked for me... just get your screen position and keep tapping it.
private const UInt32 MOUSEEVENTF_LEFTDOWN = 0x0002;
[DllImport("user32.dll")]
private static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint dwData, uint dwExtraInf);
// tap on a timer somewhere inside the app region
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
Related
I have bitblt a screenshot of the entire screen, and its indeed a valid BITMAP since after writing it to a file, I can clearly see its there.
Lets say I have the window handle of Calculator. I want to be able to constantly BitBlt the BITMAP (containing the desktop screenshot) onto the window of Calculator so that whenever calculator is open, whether its the background window (visible or overlapped by other windows) or foreground - It will always show the latest screenshot instead of the default Calculator application & its buttons.
I took a screenshot (bitmap) of the desktop and expected to use StretchDIBits to cover the region of the target application with my bitmap. However, when calculator is opened, nothing happens to it/it doesnt get replaced by the screenshot of the desktop, although the StretchDIBits function still returns the number of scan lines copied to the destination.
void* calculator_hwnd = (void*) FindWindowA("ApplicationFrameWindow", "Calculator");
void* composition_window = GetWindowDC((HWND)GetDesktopWindow());
if (composition_window)
{
void* composition_environment = 0;
if ((composition_environment = CreateCompatibleDC((HDC)composition_window)))
{
int window_x_axis = GetSystemMetrics(SM_CXVIRTUALSCREEN);
int window_y_axis = GetSystemMetrics(SM_CYVIRTUALSCREEN);
void* bitmap = CreateCompatibleBitmap((HDC)composition_window, window_x_axis, window_y_axis);
if (bitmap)
{
void* composition_bitmap = SelectObject((HDC)composition_environment, bitmap);
int status = PrintWindow((HWND) GetDesktopWindow(), (HDC)composition_environment, 0x00000002);
if (!status)
BitBlt((HDC)composition_environment, 0, 0, window_x_axis, window_y_axis, (HDC)composition_window, 0, 0, SRCCOPY);
BITMAPINFO* pbi = CreateBitmapInfoStruct((HBITMAP)bitmap);
BITMAPINFOHEADER* pbih = (PBITMAPINFOHEADER)pbi;
unsigned char* lpBits = (LPBYTE)GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);
GetDIBits((HDC)composition_environment, (HBITMAP)bitmap, 0, (WORD)pbih->biHeight, lpBits, pbi,
DIB_RGB_COLORS);
void* calculator_window_environment = GetDC((HWND)calculator_hwnd);
StretchDIBits((HDC)calculator_window_environment, 0, 0, window_x_axis, window_y_axis, 0, 0, window_x_axis, window_y_axis, lpBits, pbi, DIB_RGB_COLORS, SRCCOPY);
GlobalFree(lpBits);
SelectObject((HDC)composition_environment, composition_bitmap);
DeleteObject(bitmap);
}
}
DeleteDC((HDC)composition_environment);
ReleaseDC((HWND)GetDesktopWindow(), (HDC)composition_window);
}
This is where I got CreateBitmapInfoStruct
This question says what I am trying to do is possible, but doesn't explain how - can anyone answer that with respect to my code?
This isn't supported by the OS. Window rendering is at the discretion of the window owner (i.e. the thread that called CreateWindowEx), and there aren't any customization points external threads or processes can hook into.
While you can render into a device context that belongs to a foreign window, there's no way for you to (reliably) find out when you need to update, nor is there any way to let the destination know that it shouldn't overwrite part or all of the window contents you just rendered.
That's as far as GDI rendering goes, which is really only supported for compatibility with applications that haven't been updated to take advantage of desktop composition (introduced in Windows Vista). With this model, applications can choose to render window contents without ever providing a redirection surface (which is required if you wish to BitBlt/StretchBlt into a device context).
So, in essence, there's no way for you to reliably render onto a window you did not create. The common workaround is to create a (partially transparent) overlay window, which you would then move around to keep it in sync with the window it is supposed to augment. This is undoubtedly going to create a pretty poor user experience, as your contents are inevitably going to lag behind as the user moves the window.
I'm sending keystrokes to an inactive Adobe Flash Projector window with PostMessage, that part works perfectly. I leave it running in the background and it interferes very little with my normal computer usage, which is the intent. The problem comes when I programmatically send the W (or less frequently Q) key while I happen to be holding Ctrl intended for a different windows shortcut. This triggers Ctrl-Q or Ctrl-W, both of which immediately close the Adobe Flash Projector. Ctrl-F and Ctrl-O have some undesirable effects as well.
EDIT: I'm not interested in solutions that briefly release the Ctrl key.
Is there anyway I can unhook shortcut keys from a third party window? It uses a standard OS menubar across the top of the window which is where the shortcuts are listed, so surely there's a way to reassign, unassign, or block it, right?
In the past I tried using these dlls to break the menu. It made it disappear but didn't break the shortcuts.
DllCall("SetMenu", uint, this.id, uint, 0)
hMenu := DllCall("GetSystemMenu", "UInt",this.id, "UInt",1)
DllCall("DestroyMenu", "Uint",hMenu)
Sorry for the strange syntax, this is from an early version of my program written in autohotkey.
The language I'm using now is C#, but I assume the solution uses a .dll, so that's not as important. Feel free to suggest or change my tags.
You can try to make inactive (WS_DISABLED - use GetWindowStyle and SetWindowStyle) the main window of destination application (the Window that contains menu).
You can try to find which functions are used by application and rewrite them in local copy of application with VirtualProtect and injecting assembler (dangerous if you have no knowledge about virtualization of memory). Check the application use GetKeyState or GetAsyncKeyState (it will be visible after opening the application in text editor).
You can try:
HMENU hMenu=GetMenu(applicationMainWindow);
SetMenu(applicationMainWindow,0);
// here send your input with SendMessageW instead of PostMessageW
SetMenu(applicationMainWindow,hMenu);
Each program can use various methods to handle user keyboard input. In this case probably is used GetAsyncKeyState or GetKeyState (for Ctrl) if you didn't send it and Ctrl is detected.
If it won't help you, please add code with your PostMessage to your question.
BTW. Instead of destroying GetSystemMenu you can clear appropriate window style and after sending input restore it (if the problem is System Menu - probability near 1%).
Using the program Resource Tuner's free trial, I opened up flashplayer_28_sa.exe, went to Accelerator Table (Apparently accelerator means shortcut in the context of Menus), and deleted the offending shortcuts. Then I saved it, and it failed to save, and I saved it again, and again, and again, and then it worked, although I did nothing differently that time.
I think it would work with other shortcuts for programs with standard windows menus.
Although I didn't end up using this method, (because changing the menus was ineffectual for blocking the shortcuts for those menu items), I found various interesting ways to modify a third party window's menus. I'll leave some of what I found here because while it relate to my question, it doesn't solve my problem. Comments are based on my fallible understanding of what they do.
Various externals:
[DllImport("user32.dll")]
//get hMenu of the window's menu
static extern IntPtr GetMenu(IntPtr hWnd);
[DllImport("user32.dll")]
//Attach hMenu to a window. if hMenu is 0, attach no menu (remove menu)
static extern bool SetMenu(IntPtr hWnd, IntPtr hMenu);
[DllImport("user32.dll")]
//Destroy hMenu
private static extern bool DestroyMenu(IntPtr hMenu);
[DllImport("user32.dll")]
//Destroy Destroy submenu at position within menu
private static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);
[DllImport("user32.dll")]
//Like GetMenu, but gets the restore/move/size/minimize/etc menu that you get when clicking on the little icon in the top left of a window (not the window's menu
private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll")]
//Adds a menu to a menu
private static extern bool AppendMenu(IntPtr hMenu, int uFlags, int uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
//Removes a menu from a menu
private static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, int uFlags);
[DllImport("user32.dll")]
//Like AppendMenu, but specifies position
private static extern bool InsertMenu(IntPtr hMenu, int uPosition, int uFlags, int uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
//Lets you set various properties of a menu (grayed out, checked, etc)
private static extern bool ModifyMenu(IntPtr hMenu, uint uPosition, uint uFlags, IntPtr uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
//gets the hMenu for a submenu
private static extern IntPtr GetSubMenu(IntPtr hMenu, int pos);
Notes on their parameters:
hWnd is the handle of a window with a standard menu.
hMenu is the menu handle, which can be the handle of the root level menu (Like File, Edit, Help) or a submenu item (Like open, copy, About ...). You can get these with GetSubMenu or GetSystemMenu or
uPosition is an integer position, 0 being the first one.
uFlags can be found on each function's individual page which you can find at https://msdn.microsoft.com/en-us/library/ff468865%28v=vs.85%29.aspx
lpNewItem refers to the string of text shown on the menu item.
uIDNewItem is a pointer like hMenu that will get inserted at the defined location
I am writing a program that automates saving data to a specific location, based on the common Save/Save As dialog.
There are two attacking approaches. Both approaches require monitoring handles for messages under Spyxx (so essentially we are trying to replicate the SendMessage)
The first approach to set the File Name with target path, using Win32 SendMessage API. The HWnd in this case is the Edit field next to the File name.
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, [MarshalAs(UnmanagedType.LPStr)] string lParam);
SendMessage(HWnd, (int)WindowMessage.WM_SETTEXT, IntPtr.Zero, #"Address: %UserProfile%\Desktop\Target.txt");
The problem with this approach is that, it does not always set the text under Windows 7 and Windows 8.1 (I do have better luck with Windows 10). I tried to set some waiting time, but no matter how long I wait, it doesn't seem to matter (besides SendMessage is synchronous operation, so text should be set, or not set at all)
The second approach is to set the Location at the top of the dialog box. Again, we are using SendMessage to accomplish this, and HWnd in this case, references the ToolbarWindow32 object, which is the child of Breadcrumb Parent object.
SendMessage(HWnd, (int)WindowMessage.WM_SETTEXT, IntPtr.Zero, #"Address: %UserProfile%\Desktop");
or
SendMessage(HWnd, (int)WindowMessage.WM_SETTEXT, IntPtr.Zero, #"Address: Desktop"); // replicated message found on Spyxx
Unfortunately, this approach does not seem to work (i.e. I can send the message, but Dialog doesn't change its location), and I have yet to figure out what steps I am missing.
My question, how do you use Win32 API to interact with the 3rd party app's Save As dialog, so that you can guarantee saving the file in the desired location? Much appreciated and thanks for reading!
I'm trying to create simple Powershell script on Windows 8, that will notify me via system tray notification balloon. Code is very simple:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Icon = "D:\1.ico"
$objNotifyIcon.BalloonTipIcon = "Info"
$objNotifyIcon.BalloonTipText = "I'm there"
$objNotifyIcon.BalloonTipTitle = "Hello!"
$objNotifyIcon.Visible = $True
$objNotifyIcon.ShowBalloonTip(10000)
1.ico is custom icon really existing on disc.
It works as it should except one small thing. I prefer to have taskbar on top of my window and it seems to make troubles for balloon: it is painted under taskbar (screen: https://dl.dropbox.com/u/1138313/systraybug.PNG).
I made test application in C# with notifyIcon and got same result. But another applications like Dropbox or Skydrive haven't such problem and my script with taskbar on bottom works perfect too.
I didn't find any style options in docs for NotifyIcon. Is it annoying bug or I can fix it?
Regards.
UPS: It seems, that however Dropbox app has same problem (shame on me, didn't see at first time). So this is system bug, I guess.
This is known bug in Windows. The only way you may be able to override the behavior of the taskbar is to find the handle of the balloon and then use SetWindowPos to make it topmost:
BOOL WINAPI SetWindowPos(
_In_ HWND hWnd,
_In_opt_ HWND hWndInsertAfter,
_In_ int X,
_In_ int Y,
_In_ int cx,
_In_ int cy,
_In_ UINT uFlags
);
MSDN: "A window can be made a topmost window either by setting the hWndInsertAfter parameter to HWND_TOPMOST and ensuring that the SWP_NOZORDER flag is not set, or by setting a window's position in the Z order so that it is above any existing topmost windows. When a non-topmost window is made topmost, its owned windows are also made topmost. Its owners, however, are not changed." See SetWindowPos for more info.
Another strategy is to demote the taskbar. Use this code to find the topmost window:
HWND FindMyTopMostWindow()
{
DWORD dwProcID = GetCurrentProcessId();
HWND hWnd = GetTopWindow(GetDesktopWindow());
while(hWnd)
{
DWORD dwWndProcID = 0;
GetWindowThreadProcessId(hWnd, &dwWndProcID);
if(dwWndProcID == dwProcID)
return hWnd;
hWnd = GetNextWindow(hWnd, GW_HWNDNEXT);
}
return NULL;
}
Then demote the window or set the zorder of your window higher.
I had the same problem and discovered that the shape of the balloon depend on the size of the message body.
Namely, if your message body has up to 60 chars, round-shaped balloon will be displayed, and for longer messages, new and standard square-shaped balloon will be used.
I am not using the PowerShell to interact with system tray, but WPF NiotifyIcon library for tray icon display within WPF apps.
HTH
When an application is behind another applications and
I click on my application's taskbar icon, I expect the entire application to
come to the top of the z-order, even if an app-modal, WS_POPUP dialog box is
open.
However, some of the time, for some of my (and others') dialog boxes, only the dialog box comes to the front; the rest of the application stays behind.
I've looked at Spy++ and for the ones that work correctly, I can see
WM_WINDOWPOSCHANGING being sent to the dialog's parent. For the ones that
leave the rest of the application behind, WM_WINDOWPOSCHANGING is not being
sent to the dialog's parent.
I have an example where one dialog usually brings the whole app with it and the other does not. Both the working dialog box and the non-working dialog box have the same window style, substyle, parent, owner, ontogeny.
In short, both are WS_POPUPWINDOW windows created with DialogBoxParam(),
having passed in identical HWNDs as the third argument.
Has anyone else noticed this behavioral oddity in Windows programs? What messages does the TaskBar send to the application when I click its button? Who's responsibility is it to ensure that all of the application's windows come to the foreground?
In my case the base parentage is an MDI frame...does that factor in somehow?
I know this is very old now, but I just stumbled across it, and I know the answer.
In the applications you've seen (and written) where bringing the dialog box to the foreground did not bring the main window up along with it, the developer has simply neglected to specify the owner of the dialog box.
This applies to both modal windows, like dialog boxes and message boxes, as well as to modeless windows. Setting the owner of a modeless popup also keeps the popup above its owner at all times.
In the Win32 API, the functions to bring up a dialog box or a message box take the owner window as a parameter:
INT_PTR DialogBox(
HINSTANCE hInstance,
LPCTSTR lpTemplate,
HWND hWndParent, /* this is the owner */
DLGPROC lpDialogFunc
);
int MessageBox(
HWND hWnd, /* this is the owner */
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
);
Similary, in .NET WinForms, the owner can be specified:
public DialogResult ShowDialog(
IWin32Window owner
)
public static DialogResult Show(
IWin32Window owner,
string text
) /* ...and other overloads that include this first parameter */
Additionally, in WinForms, it's easy to set the owner of a modeless window:
public void Show(
IWin32Window owner,
)
or, equivalently:
form.Owner = this;
form.Show();
In straight WinAPI code, the owner of a modeless window can be set when the window is created:
HWND CreateWindow(
LPCTSTR lpClassName,
LPCTSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent, /* this is the owner if dwStyle does not contain WS_CHILD */
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
or afterwards:
SetWindowLong(hWndPopup, GWL_HWNDPARENT, (LONG)hWndOwner);
or (64-bit compatible)
SetWindowLongPtr(hWndPopup, GWLP_HWNDPARENT, (LONG_PTR)hWndOwner);
Note that MSDN has the following to say about SetWindowLong[Ptr]:
Do not call SetWindowLongPtr with the GWLP_HWNDPARENT index to change the parent of a child window. Instead, use the SetParent function.
This is somewhat misleading, as it seems to imply that the last two snippets above are wrong. This isn't so. Calling SetParent will turn the intended popup into a child of the parent window (setting its WS_CHILD bit), rather than making it an owned window. The code above is the correct way to make an existing popup an owned window.
When you click on the taskbar icon Windows will send a WM_ACTIVATE message to your application.
Are you sure your code is passing the WM_ACTIVATE message to the DefWindowProc window procedure for processing?
Is the dialog's parent window set correctly?
After I posted this, I started my own Windows Forms application and reproduced the problem you describe. I have two dialogs, one works correctly the other does not and I can't see any immediate reason is to why they behave differently. I'll update this post if I find out.
Raymond Chen where are you!