I am trying to open a browser through my application but I do not want it to run in the foreground and steal the focus from my application.
The code:
case WM_COMMAND:
{
SHELLEXECUTEINFO ShExecInfo;
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = NULL;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = L"open";
ShExecInfo.lpFile = L"http://www.microsoft.com";
ShExecInfo.lpParameters = NULL;
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
ShellExecuteEx(&ShExecInfo);
SetForegroundWindow(hwnd);
}
return 0;
In my application, there is a button which is sending the command message to execute the opening code, but my application goes to the background and the browser comes to the foreground.
How to solve this problem?
I suggest you start the browser using CreateProcess() instead and in the STARTUPINFO structure you initialize, use STARTF_USESHOWWINDOW in the dwFlags and in wShowWindow, be sure to include the SW_SHOWNOACTIVATE flag. That should allow the process to start but not become the active window.
Related
want to implement an auto unlock credential.
I used the SampleV2CredentialProvider demo, and wrote the account password in the "CSampleCredential::Initialize" as follow
hr = SHStrDupW(L"mypassword", &_rgFieldStrings[SFI_PASSWORD]);
and change the *pAutoLogin= true in SetSelected.
however the "sign in" window pop up, I couldn't directly login in the system without click the button.
I also changed the *pbAutoLogonWithDefault = true in the CSampleProvider::GetCredentialCount, but the button still pop up.
I have just checked code of one of my Credential Providers.
Inside of ICredentialProvider::GetCredentialCount method I do the following:
DWORD dwSize;
*pdwCount = 0;
*pdwDefault = -1;
*pbAutoLogonWithDefault = FALSE;
dwSize = 0;
// do some internal calculations
if(dwSize > 0)
{
*pdwCount = 1;
*pdwDefault = 0;
*pbAutoLogonWithDefault = TRUE;
}
Iside of ICredentialProviderCredential::SetSelected i do only this:
*pbAutoLogon = TRUE;
Everything is working fine.
(The code snippets are exactly copy-paste from real project)
I'm writing an application in C# to remote control another application. I don't have access to that application yet, but it's most likely written in either Visual C++ or VB6. I'm currently remote controlling a simple C# winforms program I created instead. So far, I can get all of the controls in a manner similar to Spy++ using PInvoke. I can also do things like setting the text in a textbox. The problem I have is that I can't uniquely identify a specific text box between executions of the application I'm controlling. I can't use hWnd for example because it's different every time you run the application. GetWindowLong returns whatever the hWnd is so that's no help. The internet speaks of this message called WM_GETCONTROLNAME. The scary code below attempts to use that message to get the name the developer used to uniquely identify the controls. The SendMessage seems like it's returning the number of bytes in the name. But the buffer containing that name comes back all zeros.
So here's the question. How can I fix the code below so that it returns that name correctly? (Hopefully it's a boneheaded mistake that's easy to fix) Or, just as good, is there some other ID that will be guaranteed to be the same every time I run the program? Without something to uniquely identify the textbox controls, my code can't tell them apart.
I do have a hack in mind. It seems to me that using the position of the textboxes to tell them apart would work. But I'd much prefer to have the code below working.
public static string GetWindowText(IntPtr Handle)
{
int BufferSize = 256;
uint Message = RegisterWindowMessage("WM_GETCONTROLNAME");
StringBuilder sb = new StringBuilder(BufferSize);
byte[] ControlName = new byte[BufferSize];
long BytesRead = 0;
IntPtr BytesReadPointer = new IntPtr(BytesRead);
IntPtr OtherMem = IntPtr.Zero;
try
{
OtherMem = VirtualAllocEx(Handle, IntPtr.Zero, new IntPtr(sb.Capacity), AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
var Result = SendMessage(Handle, Message, new IntPtr(sb.Capacity), OtherMem);
//Result contains different numbers which seem like the correct lengths
var Result2 = ReadProcessMemory(Handle, OtherMem, ControlName, BufferSize, out BytesReadPointer);
//ControlName always comes back blank.
}
finally
{
var Result3 = VirtualFreeEx(Handle, OtherMem, BufferSize, FreeType.Release);
}
return ""; // Convert ControlName to a string
}
So after a good night's sleep and a little tinkering, I managed to fix the problem myself. There were two problems. First, I was passing in the handle to the control to VirtualAllocEx. But in the documentation for that function, it says that it takes a handle to the process. So started supplying that. Then VirtualAllocEx was telling me that I had an invalid handle. So it turns out the handle you pass to VirualAllocEx has to have PROCESS_VM_OPERATION set. So I made a call to OpenProcess to get that handle, then passed that to VirtualAllocEx. After that, everything worked. I just had to convert the byte array coming back into a string, and trim a bunch of nulls. This returns the Name property on the controls. I'll post the code here in case anyone else needs something like this.
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VirtualMemoryOperation = 0x00000008,
VirtualMemoryRead = 0x00000010,
VirtualMemoryWrite = 0x00000020,
DuplicateHandle = 0x00000040,
CreateProcess = 0x000000080,
SetQuota = 0x00000100,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
QueryLimitedInformation = 0x00001000,
Synchronize = 0x00100000
}
public static string GetWindowText(IntPtr ControlHandle, IntPtr ProcessHandle)
{
int BufferSize = 256;
StringBuilder sb = new StringBuilder(BufferSize);
byte[] ControlNameByteArray = new byte[BufferSize];
long BytesRead = 0;
IntPtr BytesReadPointer = new IntPtr(BytesRead);
IntPtr RemoteProcessMemoryAddress = IntPtr.Zero;
IntPtr RemoteProcessHandle = IntPtr.Zero;
try
{
uint Message = RegisterWindowMessage("WM_GETCONTROLNAME");
RemoteProcessHandle = OpenProcess(ProcessAccessFlags.CreateThread |
ProcessAccessFlags.QueryInformation |
ProcessAccessFlags.VirtualMemoryOperation |
ProcessAccessFlags.VirtualMemoryWrite |
ProcessAccessFlags.VirtualMemoryRead, false, Process.Id);
RemoteProcessMemoryAddress = VirtualAllocEx(RemoteProcessHandle, IntPtr.Zero, new IntPtr(sb.Capacity), AllocationType.Commit, MemoryProtection.ExecuteReadWrite);
if (RemoteProcessMemoryAddress == IntPtr.Zero)
{
throw new Exception("GetWindowText: " + GetLastWin32Error());
}
SendMessage(ControlHandle, Message, new IntPtr(sb.Capacity), RemoteProcessMemoryAddress);
ReadProcessMemory(RemoteProcessHandle, RemoteProcessMemoryAddress, ControlNameByteArray, BufferSize, out BytesReadPointer);
string ControlName = Encoding.Unicode.GetString(ControlNameByteArray).TrimEnd('\0');
return ControlName;
}
finally
{
VirtualFreeEx(RemoteProcessHandle, RemoteProcessMemoryAddress, BufferSize, FreeType.Release);
}
}
Here is an example code which sends a mouse click (using xlib). For simplicity events are sent to the fullscreen window (root and window coordinates are the same) and window id is obtained using wmctrl.
Display *display = XOpenDisplay(NULL);
XWarpPointer(display, None, RootWindow(display, DefaultScreen(display)), 0, 0, 0, 0, 300, 200);
XEvent event;
memset(&event, 0x00, sizeof(event));
event.type = ButtonPress;
event.xbutton.button = button;
event.xbutton.same_screen = True;
event.xbutton.root = RootWindow(display, DefaultScreen(display));
event.xbutton.window = 81788929;
event.xbutton.subwindow = 0;
event.xbutton.x_root = 300;
event.xbutton.y_root = 200;
event.xbutton.x = 300;
event.xbutton.y = 200;
event.xbutton.state = 0;
XSendEvent(display, PointerWindow, True, ButtonPressMask, &event);
XFlush(display);
XCloseDisplay(display);
Above code works fine. I ported it to xcb:
Display *display = XOpenDisplay(NULL);
XWarpPointer(display, None, RootWindow(display, DefaultScreen(display)), 0, 0, 0, 0, 300, 200);
xcb_button_press_event_t event;
memset(&event, 0x00, sizeof(event));
event.event = 81788929;
event.same_screen = 1;
event.root = RootWindow(display, DefaultScreen(display));
event.root_x = 300;
event.root_y = 200;
event.event_x = 300;
event.event_y = 200;
event.child = 0;
event.state = 0;
xcb_connection_t *conn = XGetXCBConnection(display);
xcb_send_event(conn, false, 81788929, XCB_EVENT_MASK_BUTTON_PRESS, (char*)(&event));
xcb_flush(conn);
XCloseDisplay(display);
XCB code doesn't work: destination window doesn't get any event. What is wrong ?
Edit1
When I use following code for a connection:
xcb_connection_t *conn;
xcb_screen_t *screen;
conn = xcb_connect (NULL, NULL);
screen = xcb_setup_roots_iterator (xcb_get_setup (conn)).data;
and later:
event.root = screen->root;
it also doesn't work.
Nowhere in your code there are error checks. Anyway, I suspect that XGetXCBConnection(display); does not return you a valid Xcb connection. Why you may ask? Because for this to work Xlib must have been built as a wrapper around Xcb and the internal structures properly been set up.
I suggest you create the connection and open the display purely with Xcb and see if this solves the problem.
I run test program windows8 or 7 64/32bit
but i can't capture screen when running virtual desktop
here is my code
hwnd h1 = createwindows(....) or dialog.. //if this line remove capture code works fine
hDesktopCurrent = NULL;
hOriginalInput = NULL;
hDesktopCurrent = GetThreadDesktop(GetCurrentThreadId());
hOriginalInput = OpenInputDesktop(0, FALSE, DESKTOP_SWITCHDESKTOP);
hDeskVirtual= NULL;
attr.nLength = sizeof(attr);
attr.lpSecurityDescriptor = NULL;
attr.bInheritHandle = true;
hDeskVirtual= CreateDesktopEx(
"my_new_desktop_1",
NULL,
NULL,
0,
GENERIC_ALL,
&attr,
0,
NULL);
SwitchDesktop(hDeskVirtual);
SetThreadDesktop(hDeskVirtual);
//capture here
SwitchDesktop(originaldesktop);
SetThreadDesktop(originaldesktop);
ps:
When I nerver create any windows hwnd before switchdesktop
(ex:createwindows,creatdialog...) it works perfertly capture..
but I create any windows frame or dialog,
it didn't work
that only captured BlackScreen
plz..help me!
CaptureScreenApp app;
int MyPluginAPI::captureScreen(const FB::JSObjectPtr& callback)
{
boost::thread cs(boost::bind(&CaptureScreenApp ::captureScreen,
app, callback));
return 1;
}
class CaptureScreenApp {
public:
CaptureScreenApp() {
HRESULT hRes;
hRes = OleInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));
AtlInitCommonControls(ICC_WIN95_CLASSES);
g_Module.Init(NULL, NULL);
};
~CaptureScreenApp() {
g_Module.Term();
OleUninitialize();
};
bool captureScreen() {
CMessageLoop theLoop;
CMainDialog g_MainDlg;
g_Module.AddMessageLoop(&theLoop);
if (NULL == g_MainDlg.Create(NULL)){
DWORD ret = GetLastError();
return FALSE;
}
g_MainDlg.ShowWindow(SW_SHOW);
g_MainDlg.UpdateWindow();
int nRet = theLoop.Run();
g_Module.RemoveMessageLoop();
return TRUE;
};
};
class CMainDialog : public CDialogImpl<CMainDialog>
{
public:
enum {IDD = IDD_MAIN};
....
}
the window(the new window is a full screen window with a desktop pic as the background) I create in CaptureScreenApp::captureScreen always under the browser window when it appears(browser window always actived in other word), what ever how I set the HWND_TOPMOST for the new window. like this:
enter link description here
how can i bring the full screen window to top when it appers?
SetWindowPos API lets you change Z order (make sure to read Remarks there). You create your window with NULL parent, so your window is completely independent from browser window, so there is nothing to push it to the front: it would be either you or interactive user.