Unable to check a checkbox using C# WinAPI - c#

I'm trying to check a checkbox inside a program called AviReComp and I'm unable to do it somehow. I've tried all sorts of code:
//Check the checkbox
IntPtr SubtitlesSection = FindWindowEx(MoreOptions, IntPtr.Zero, null, "Subtitles");
IntPtr AddSubtitlesCheckbox = FindWindowEx(SubtitlesSection, IntPtr.Zero, null, "Enable/Disable");
SendMessage(AddSubtitlesCheckbox, BM_SETSTATE, 1, IntPtr.Zero);
SendMessage(AddSubtitlesCheckbox, BM_SETCHECK, 1, IntPtr.Zero);
SendMessage(AddSubtitlesCheckbox, WM_PAINT, 0, IntPtr.Zero);
SendMessage(AddSubtitlesCheckbox, WM_LBUTTONDOWN, 1, MakeLParam(10, 10));
SendMessage(SubtitlesSection, WM_PARENTNOTIFY, (int)MakeLParam((int)AddSubtitlesCheckbox, WM_LBUTTONDOWN), MakeLParam(26, 31));
SendMessage(SubtitlesSection, WM_PARENTNOTIFY, (int)MakeLParam((int)AddSubtitlesCheckbox, WM_LBUTTONUP), MakeLParam(26, 31));
The checkbox is located within the Additions tab underneath the Subtitles section and is called Enable/Disable.
Am I doing something wrong?
Thanks for any help!
Edit: I now see that this code actually works and it does check the checkbox but I still have a problem since it does not change all the controls that are supposed to change when I check the checkbox manually and not inside my program. Is there a way to force the parent control to repaint itself or trigger the change event when I mark the checkbox as checked?

try to use spy++ to make sure of the location of the Check-box if all didn't work and this has to run on vista and above I Would use Windows Automation

When the state of a child control changes (in response to a user action), it sends some notification messages to it's parent window, and parent window by catching those messages, performs actions. Those notification messages are WM_COMMAND and WM_NOTIFY.
By monitoring messages sent to the parent window of your check box control (and checking the control by mouse), I noticed one WM_COMMAND message and two WM_NOTIFY messages. Those messages where not available when I programmatically sent a BM_SETCHECK message to the check box. So the magic revealed.
Sending WM_NOTIFY is a little difficult, because you have to allocate memory in the address space of the other process (using VirtualAllocEx, for NMHDR structure), fill the memory (using WriteProcessMemory), send the message, and then release the allocated memory.
Sending WM_COMMAND message is too much simpler. I tested it, and it worked!
Win32.SendMessage(SubtitlesSection, Win32.Message.WM_COMMAND, 0, AddSubtitlesCheckbox);
The message is sent to the parent control of the check box, using the handle of the control as the fourth parameter. Third parameter of the function should be the control ID, and the ID changes every time. But hopefully it seems that the program checks the control handle and not the ID.

Related

How to disable mouse wheel event in another application(WM_MOUSEWHEEL) using Handler

I am able to close another application window (calculator) from my application by using the following code:
hwnd = FindWindow(null, "Calculator");SendMessage(hwnd,WM_CLOSE,0,IntPtr.Zero);
But I want to disable the mouse wheel in the same calculator application window. I tried the following way, but it doesn't work:
SendMessage(hwnd, WM_MOUSEWHEEL, 0, IntPtr.Zero);
You need to Hook Into the Event and catch the occurence if you want to disable it for specific hWnds.
Look into this:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd373640(v=vs.85).aspx
If you define your callback function, it does need to take care about the correct distribution of the events to all Windows except the one you are searching for, despite that I'm not sure if this is just a clone of the Eventmessage or if they are only directed to your application if the hook is set.
Important is also that the code provided in the example is not complete,
it is missing a message-loop which actually does the grabbing from the message-queue.
Edit
the link mentioned below
http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/

Windows API Call CB_SELECTSTRING

We have a C# 2012 WCF service that is interacting with a desktop application that is built in VB6 no less and are having issues with a drop down selection using Windows API calls.
The way the application works when you are actually working within it is that you select an entry in a drop down box first. Then enter information in text boxes below it. You select another entry in the drop down box, the fields reset to blank text boxes. The code behind on the downstream application associates the text box information with the selection in the drop down. That is way that particular app works.
Our problem is automating this process. We use Win32 API calls to set information in the drop down using the following:
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, [Out] int wParam, string lParam);
// Actual call to the downstream app.
SendMessage(hWnd, (int)CB_SELECTSTRING, 0, strValue);
The problem is when we try to set the second value in the drop down box. The text boxes are not being reset. We have tried using the following calls as well:
SendMessage(hWnd, (int)CB_SELECTSTRING, -1, strValue);
SendMessage(hWnd, (int)CB_SETCURSEL, 0, strValue);
SendMessage(hWnd, (int)CB_SETCURSEL, -1, strValue);
None of these messages are accomplishing the task. We need the call to simulate the Selected Index Changed event. Are we not using the right piece here? Or do we need to send a message to the parent to fire off that event?
I looked through our solution and did not find CBN_SELCHANGE anywhere or any API call that would send that to the parent.
Any ideas here folks?
I am not sure that the notification CBN_SELCHANGE should be fired in this case. Once you change something in the combobox programmatically, it will be easier for you to change whatever else on the form from the next line of your code. Doing same thing threw the notification only complicates the code. Think as if you are writing the code of this form.
Once you are able to access the hWnd of the combobox, you maybe should update your entry fields as well using the same SendMessage.
Other approach - send the CBN_SELCHANGE yourself. There is nothing against that. This is simply a message.
The CB_SETCURSEL is not using the LPARAM. You should pass 0 there.
You should also recheck how .Net marshalls your string. I am not sure this will be so simple. To verify this build your own small dll, check definition to DllImport("myUser32.dll") and put a breakpoint in the debugger at the entry of your dummy SendMessage. You will see what comes to the native code.

Finding the IntPtr of the TaskBar

Previously, I asked this question about returning the user to the previous window they were using, but I have found the solution, but it has created another problem. The function that determines the previous window will sometimes work (if a certain set of events happen that I cannot recreate at will, but happens randomly). At some point it goes 2 windows back, sometimes 1 window back. It does this because the taskbar is in the way first, and then there is the window.
So, in order to fix this, I have determined that I should keep going through the previous windows until I get to a window that is not the taskbar, however, I do not know how to determine the IntPtr of the taskbar.
I have tried:
IntPtr taskBarWnd = FindWindow("Shell_TrayWnd", null);
But it doesn't seem to work. If I call MessageBox.Show(taskBarWnd.ToInt64().ToString()), I get 131258, but when I do:
IntPtr thisWnd = GetForegroundWindow();
IntPtr lastWnd = GetWindow(thisWnd, 2);
It is referencing the taskbar, but when I call the same MessageBox function above, it returns 131260 (65774 if the icon is within the hidden icons area).
Does anyone know if there is anything else I can try to determine if the lastWnd I have calculated is the taskbar? I would prefer not to have something that checks if the IntPtr's are close to each other instead of being equal.
I can't check right now since this is my iPad, but I'm pretty sure the taskbar windows all use custom window classes so you should be able to call GetClassName and figure out from the result what your handle refers to.

Detect change of focus and find it C#

I need an underlying process to gather information about other applications used by Windows. I suspect this would be done using WAPI hooks. What I wish to do is for my program to detect when windows changes focus from one program to another and tell me which one currently has focus.
First I need an event that triggers each time Windows swaps focus between two applications. All events I've found so far only handles changes made from or to the program it's being used by, but I need to find all focus-changes, even if it's between two other programs.
I'll also need a function that gives me the window in focus. Would this work, or is this only internally (windows within the current application and not other programs)?
Cheers
Depending on how accurate you need your focus change detection system to be you might be able to get away with a service that polls for the foreground window using the API function you described GetForegroundWindow (yes this is system-wide, not process specific).
You can then use the handle of that function to determine which process is the current active/focused process. Then retrieve the focused element (child window) of that process..
HWND hwnd = GetForegroundWindow();
DWORD remoteThreadId = GetWindowThreadProcessId(hwnd, NULL);
DWORD currentThreadId = GetCurrentThreadId();
AttachThreadInput(rThreadId, curThreadId, TRUE);
HWND focusElement = GetFocus();
AttachThreadInput(rThreadId, curThreadId, FALSE);
Keep doing this.. and do whatever you need to do with focusElement
UPDATE
Well, apparently, as #Kenneth K. posted in a comment, there is a global EVENT_SYSTEM_FOREGROUND event that you can hook so that you application gets notified when the foreground (focused) window changes. This way you don't need to loop continuously to detect these changes.
EVENT_SYSTEM_FOREGROUND = 3;
WINEVENT_OUTOFCONTEXT = 0;
You can follow the example in this answer to see how to hook this event and get the notifications. Then whenever the foreground (focused) window changes you can hook that window's message loop and look form focus changed events withing that window using the SetWindowsHookEx function.
Another options is to consult the list of system events on MSDN and see if there is one you can use instead of the EVENT_SYSTEM_FOREGROUND, or along with it to detect control-level focus events. Perhaps the EVENT_OBJECT_FOCUS might be useful.
Please let me know if this is still unclear..

Simulate keypress in a non-visible webbrowser object C#

I'm currently working in an application that has to navigate a webpage and recollect data about products, prices, ... with webbrowser object in .net 3.5.
The problem is that the page has some fields with a suggest script in ajax, and I can't simply modify the innerText property because the script also saves codes in a hidden input field.
I need a way to simulate the typing in that field and then send the "Enter" key, or launch the ajax script and then send the "Enter" key, or any better ways to do this.
Use Watin
Then you can use this solution.
To submit a form or run a script you can do this:
If you know the script name you can use InvoekScript of Document object:
myWebBrowser.Document.InvokeScript("script-name",null);
the second argument is an array of objects to pass parameters values.
if you know the name of an element that it's click event fires the script you can do this:
HtmlElement element=myWebBrower.Document.GetElementById("element-name")[0];
element.InvokeMember("click");
There are a few ways to do this with the standard WebBrowser control.
For HTML: If you want to fillout a textbox and then click submit then don't even bother with a keypress. Do this:
webbrowser1.Navigate("javascript:function%20E(){f0=document.forms[0];f0['login'].value='foo';}E()")
webbrowser1.Navigate("javascript:document.forms[0].submit()")
This will be much more reliable then trying to send keypresses for HTML.
**For Flash:**If there's a flash element on the webpage that needs clicking then it won't work. In that case SendKeys is reliable but only sends to the active application so it won't work in the background. You can send windows messages like this (example will press the letter "f"):
Dim c as char = "f"c
Dim classname As New System.Text.StringBuilder(100)
Dim ExplorerHandle As IntPtr = webbrowser1.Handle
GetClassNameA(ExplorerHandle, classname, classname.Capacity)
Do While classname.ToString <> "Internet Explorer_Server"
ExplorerHandle = GetWindow(GetExplorerHandle, GetWindow_Cmd.GW_CHILD)
GetClassNameA(ExplorerHandle, classname, classname.Capacity)
Loop
PostMessageA(ExplorerHandle, WM_Constants.WM_KEYDOWN, IntPtr.Zero, IntPtr.Zero)
PostMessageA(ExplorerHandle, WM_Constants.WM_KEYUP, CType(VkKeyScanA(CType(Asc(c), Byte)), IntPtr), IntPtr.Zero)
You can find the definitions for PostMessage, GetClassName, GetWindow, etc, online at pinvoke.net. Notice that the WM_KEYUP uses c but the WM_KEYDOWN sends a dummy key (0). KEYDOWN and KEYUP have to go in pairs or else the key won't be registered, but if you hold down Control while sending, for example, KEYDOWN "p", it will activate IE's print function. For all the letters and digits you can send 0 for KEYDOWN and the correct letter for KEYUP. Backspace seems to need a real KEYDOWN, not 0, but Control-Backspace doesn't seem to do much in IE so if c = vbBack, KEYDOWN needs to be different.
The keypresses aren't very accurate, either, and 1 time in about 500 it misses. But you can do it with the window minimized, no problem, and a standard WebBrowser control.
Another option is to use AxWebBrowser. The ActiveX control seems to avoid the Control-P problem but it's not as easy to manipluate because it isn't a nice .Net control.

Categories

Resources