|
Looks like it will only work if you have a single a keyboard sender (controller)
Unfortunately, my case is more complicated.
I need to run several keyboard senders each of which control/automate a separate window application.
The senders are independent and not synchronized, so with this solution they will compete each other to make their own controlled windows foreground. So, there is no guarantee that a key sequence will reach a proper window, since sequences are really directed to a currently active window but not to a specific window by given handle.
|
|
|
|
|
There can be only a sender at one time. There is no other way. But multiple senders can be synchoronized with this class. Use void SetReActivate (true, 3000);
This will allow all the senders to send their keystrokes to the correct window. Note that the second parameter should not be 0. Otherwise, the senders may enter an infinite loop.
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
I just did some changes in order to compiling it with VS .NET
I don't see the way to attach a file with this message, so I just report the changes:
---------------------
dd:\Projs\KeyTest\MiscCtrls.cpp(3) : fatal error C1083: Cannot open include file: '../src/afximpl.h': No such file or directory
#if (_MSC_VER < 1300)
#include "../src/afximpl.h"
#else
#include "../src/mfc/afximpl.h"
#endif
---------------------
d:\Projs\KeyTest\KeyTest.cpp(50) : warning C4996: 'CWinApp::Enable3dControls' was declared deprecated
#if (_MSC_VER < 1300)
# ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
# else
Enable3dControlsStatic(); // Call this when linking to MFC statically
# endif
#endif
---------------------
d:\Projs\KeyTest\MiscCtrls.cpp(57) : error C2039: 'bWin4' : is not a member of 'AUX_DATA'
c:\Program Files\Microsoft Visual Studio .NET\Vc7\atlmfc\src\mfc\afximpl.h(54) : see declaration of 'AUX_DATA'
#if (_MSC_VER < 1300)
ASSERT(afxData.bWin4);
#else
ASSERT(!afxData.bWin95);
#endif
d:\Projs\KeyTest\MiscCtrls.cpp(64) : error C2039: 'bWin4' : is not a member of 'AUX_DATA'
c:\Program Files\Microsoft Visual Studio .NET\Vc7\atlmfc\src\mfc\afximpl.h(54) : see declaration of 'AUX_DATA'
#if (_MSC_VER < 1300)
ASSERT(!afxData.bWin4);
#else
ASSERT(afxData.bWin95);
#endif
d:\Projs\KeyTest\MiscCtrls.cpp(68) : error C2039: 'bWin4' : is not a member of 'AUX_DATA'
c:\Program Files\Microsoft Visual Studio .NET\Vc7\atlmfc\src\mfc\afximpl.h(54) : see declaration of 'AUX_DATA'
#if (_MSC_VER < 1300)
if (afxData.bWin4)
#else
if (!afxData.bWin95)
#endif
d:\Projs\KeyTest\MiscCtrls.cpp(78) : error C2039: 'bWin4' : is not a member of 'AUX_DATA'
#if (_MSC_VER < 1300)
if (!afxData.bWin4)
#else
if (afxData.bWin95)
#endif
because only the bWin95 data member survived:
----------------------
d:\Projs\KeyTest\MiscCtrls.cpp(644) : error C2360: initialization of 'pts' is skipped by 'case' label
just enclose all the case label WM_MBUTTONDOWN inside a block, i.e. with { and }
----------------------
d:\Projs\KeyTest\MiscCtrls.cpp(1418) : error C2440: 'static_cast' : cannot convert from 'void (__thiscall CSystemTray::* )(WPARAM,LPARAM)' to 'LRESULT (__thiscall CWnd::* )(WPARAM,LPARAM)'
void OnTaskbarCreated(WPARAM wParam, LPARAM lParam); -> LRESULT OnTaskbarCreated(WPARAM wParam, LPARAM lParam);
at miscctrls.h line 789
and
void CSystemTray::OnTaskbarCreated(WPARAM /*wParam*/, LPARAM /*lParam*/) -> LRESULT CSystemTray::OnTaskbarCreated(WPARAM /*wParam*/, LPARAM /*lParam*/)
at miscctrls.cpp line 1444
----------------------
d:\Projs\KeyTest\MiscCtrls.cpp(1651) : error C2660: 'CWnd::DrawAnimatedRects' : function does not take 4 parameters
d:\Projs\KeyTest\MiscCtrls.cpp(1668) : error C2660: 'CWnd::DrawAnimatedRects' : function does not take 4 parameters
DrawAnimatedRects -> ::DrawAnimatedRects
----------------------
d:\Projs\KeyTest\miscctrls.h(675) : warning C4183: 'Create': missing return type; assumed to be a member function returning 'int'
Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID, ->
BOOL Create(CWnd* pParent, UINT uCallbackMessage, LPCTSTR szTip, HICON icon, UINT uID,
at miscctrls.h line 672
----------------------
Your program is great !
Marcello
|
|
|
|
|
Hi Marcello,
Thanks a lot for the notifications. I used VS.NET for a while and because of the lack of Class Wizard, I returned back to VS6. Since i dont have VS.NET right now, i am unable to test it, but these changes will help to the .NET users. Thank you very much.
PS: I think these changes are just for the demo application. If you just want to use the base source, you dont need any changes. Right?
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Your article is good. In one of my application, i use MSDataGrid. Just like MS-Access(while deleting one or some rows, it will ask 'are you sure to delete 5 rows?') I want to do in my application. For that, i have to check whether the control is focussed on the datagrid and one or some rows are selected and check whether the user pressed 'Delete' button. I want to do this in a simple message handler function. Thanks in advance.
|
|
|
|
|
For me it does not seem to work that well
I built the sample, and tried it with notepad.
Only sometimes the keystrokes get there, the other times
it just sets focus to notepad.
Im running XP.
/Magnus
|
|
|
|
|
I havent tested these classes on XP, but they are supposed to work on all versions. I don't know what the problem is...
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
I noticed that if i check the box 'if window loses focus, auto re-activate' the keys will be sent after the specified delay.
I also tried with the command prompt, and there it worked as it should.
/Magnus
|
|
|
|
|
You can also enter "0" as the delay. By this way, the keystrokes will be sent to that window without any delay.
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
BTW, I am going to buy an XP license tomorrow. Hopefully, i get the package this week. Then I will surely test it on XP and see the results.
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Hi Magnus,
I got my XP yesterday and tested the program. As you said, it just activates Notepad and then stops. I think some window functions are changed in XP. IMHO, SetForegroundWindow () is not synchronous anymore. Because, the program class calls SetForegroundWindow and assumes that it is the foreground window after this call. However, this is not the case in XP. I dont know what , but I will have a look at this issue.
Thanks for your warning.
Happy programming
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Mustafa Demirhan wrote:
IMHO, SetForegroundWindow () is not synchronous anymore. Because, the program class calls SetForegroundWindow and assumes that it is the foreground window after this call.
Yes, I use another automation tool (AutoIt), and read the corresponding mailing list. I saw that the AutoIt author had some problems with XP (and perhaps Win2000) because these systems may forbid to make a window foreground.
I believe that's because users (like me) were upset to navigate the Start menu (or any other menu) and loose the focus and the menu because another window goes foremost...
That's a good thing, except when the users want the window to go foreground, eg. when activating a window instance (check if already open) or in automation projects.
The AutoIt author had to use 5 or 6 different methods (one by one) to be sure to get the desired window foremost. He didn't gave the algorithm But I believe he used every method in the book, testing each time if it was effective...
Regards.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
|
Well done, really
Is there a similar thing for mouse movements and clicks
planned in an upcoming release?
Or can you point me to some other reference?
Thank you.
|
|
|
|
|
Anonymous wrote:
Is there a similar thing for mouse movements and clicks
planned in an upcoming release?
Good idea Hopefully, next release will include this feature.
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Two notes:
- For automation projects, unless you have no choice (sloppy programs without shortcuts, toolbars without menu equivalent, or mouse only operations), you should use almost exclusively keyboard shortcuts, because they are resolution and window size/position independent.
- Check this article I just discovered: Tester Utility, Take 3: Adding Mouse Recording and Playback (http://msdn.microsoft.com/msdnmag/issues/02/03/Bugslayer/Bugslayer0203.asp) for useful tips on how to do this...
Regards.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Philippe Lhoste wrote:
- Check this article I just discovered: Tester Utility, Take 3: Adding Mouse Recording and Playback (http://msdn.microsoft.com/msdnmag/issues/02/03/Bugslayer/Bugslayer0203.asp) for useful tips on how to do this...
This is what I need!
Thanks a bunch man...
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Even though this article seems like advertisment for Macro Angel (judging from the number of links), I think it is fair enough since you are sharing part of your code, and an important one.
The interface (of the demo) is clean and complete. I just didn't understood how to send keys to the active window with it: I uncheck the "Send keystrokes only to the following window", activate an editor window, click on "Send Keys", and the demo closes, because it received the <enter> key!
Either I am missing something, or actually the demo cannot do that. Which is not very important, your code is the really interesting thing.
Additional possible improvements for the demo: a way to refresh the list of applications, an explaination to indicate we have to double click on this list to update the Window Title field.
It works well on WinNT4, including to send to a command window (Dos-like), which is supposedly tricky. I wonder how it behaves with Win9x Dos boxes. I have no one handy right now, but I will test it.
Note: this application doesn't send global shortcut keystrokes. For example, an icon on the Desktop can have a Ctrl+Shift+T shortkey, but when I send this sequence to an application like Explorer, it doesn't work. And I don't know (with the demo) how to send this to the Desktop, whose class is identified as SysListView32... Same problem with <lwin> or <rwin> keys. Plus I am not sure if they act on their own (ie. call the Start menu) as it seems or as modifier like the Alt/Ctrl/Shift ones (eg. using <lwin>R to call the Run dialog box).
Additional note: in your syntax, and in the demo, I see no way to quote < and > keys, ie. to send them instead of being interpreted.
Thank you.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Hi Philippe,
Philippe Lhoste wrote:
Even though this article seems like advertisment for Macro Angel (judging from the number of links), I think it is fair enough since you are sharing part of your code, and an important one.
I am really sorry for that. I will delete all the links next time I update the article.
Philippe Lhoste wrote:
I just didn't understood how to send keys to the active window with it:
In the demo program, you cant. Because, in order to run the demo program, it must be the active window. Maybe, you can add a delay at the beginning and then activate the other program
Philippe Lhoste wrote:
Additional possible improvements for the demo: a way to refresh the list of applications, an explaination to indicate we have to double click on this list to update the Window Title field.
I will do this next time I update the code. But the demo is just a small show that allows people to see what the real code can do. In general, it will not be used in the programs.
Philippe Lhoste wrote:
Note: this application doesn't send global shortcut keystrokes.
Thanks for warning me. I will try to find the problem
Philippe Lhoste wrote:
And I don't know (with the demo) how to send this to the Desktop
You cant do this with the demo program
Philippe Lhoste wrote:
Additional note: in your syntax, and in the demo, I see no way to quote < and > keys, ie. to send them instead of being interpreted.
If you just write that characters, the program will send it, as soon as you do not write a special character name, like <ctrl> or <alt>. For example, if you write <hello world="">, the program sends <hello world="">.
Thank you very much for your comments.
May be next time, I will reveal some more code from Macro Angel (and without any ads)
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
|
Hi Nish,
If I reveal all the source code of Macro Angel, I still cannot catch you . You are really doing a good job Nish.
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Thank you for your answer, I just saw it, CP didn't sent an e-mail to indicate my comment was answered
Keep the links, of course, it is informative and unobstrusive
Mustafa Demirhan wrote:
Philippe Lhoste wrote: And I don't know (with the demo) how to send this to the Desktop
You cant do this with the demo program
I understand it is just a demo, we (the programmers) have to handle these problems... Although showing a way to do it would be cool
BTW, I made some more tests with your demo:
For <LWIN> and <RWIN> to be effective, the key must be sent to the Program Manager. I cannot use these keys to activate global shortcuts like <LWIN>R launching the Run dialog.
And still, sending global shortkeys to the Program Manager don't seems to activate Desktop icon shortcuts,
<APPS> is effective when sent to an application, it activates its context menu. If it is an editor, the context menu appears where the caret is.
Mustafa Demirhan wrote:
Philippe Lhoste wrote: Additional note: in your syntax, and in the demo, I see no way to quote < and > keys, ie. to send them instead of being interpreted.
If you just write that characters, the program will send it, as soon as you do not write a special character name, like <CTRL> or <ALT>. For example, if you write <Hello world>, the program sends <Hello World>.
Note: CodeProject ate your < and >... I restore them by hand, using < and >...
That's the problem: we cannot send a reserved sequence.
As I noted down before reading your answer:
"We can send < and > using them unquoted as long as they don't match a command of the engine. I still don't see how to send them when the sequence is seen as a command."
Perhaps you should define a special character or syntax to allow sending these characters literally, in all cases. Perhaps the classical backslash, but it is annoying because of its use in the paths. Unless it is interpreted literally if not followed by < and > or \. Or simply to double these characters: <<CTRL>> will send <CTRL> while <CTRL> will be interpreted by the engine.
I am not making these remarks just to lazily get improvements to your demo/engine, but also to help you improve your product, unless you already solved these issues there.
Thank you for this great engine! I will try and make it MFC independent, and perhaps more flexible on the syntax (before 2010, as my schedule goes )
Regards.
--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--=#=--
Philippe Lhoste (Paris -- France)
Professional programmer and amateur artist
http://jove.prohosting.com/~philho/
|
|
|
|
|
Philippe Lhoste wrote:
Perhaps you should define a special character or syntax to allow sending these characters literally, in all cases. Perhaps the classical backslash, but it is annoying because of its use in the paths. Unless it is interpreted literally if not followed by < and > or \. Or simply to double these characters: <<ctrl>> will send <ctrl> while <ctrl> will be interpreted by the engine.
I will do this as soon as I finish my exams this semester
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
I've been doing windows programming for a hell of a long time. And I've written any number of applications that take input from the keyboard. However, I have always just processed the WM_KEYDOWN WM_CHAR, messages to deal with that need. That has always worked pretty well for me.
I have frequently heard people refer to keyboard hooks and keystroke engines without really understanding what they were talking about. So, why do you need a special app to send key strokes to a selected window? Isn't the selected window going to handle them by default? Mine always do. I thought the window's OS handled that.
Is the idea to be able to type into one window and have the output appear in another window/application? Or, is the idea to send 'virtual' or simulated key strokes to a selected window, i.e. I recieve a key stroke in my window and programatically send it on to another preselected application. Is that the idea? If so, why would you need to do that? I'm just curious as that is a class of problem I have apparently never encountered or maybe I've been doing things incorrectly this entire time.
"There's a slew of slip 'twixt cup and lip"
|
|
|
|
|
Hi,
I am using this in my application Macro Angel. Macro Angel is an automation program and it has an option to simulate keypresses. In order to do that, I have to send keystrokes. The idea here is that, the user types the keystrokes to be sent, and my application does it when a specific event occurs. But of course the usage is not limited to this.
Stan Shannon wrote:
Is the idea to be able to type into one window and have the output appear in another window/application? Or, is the idea to send 'virtual' or simulated key strokes to a selected window, i.e. I recieve a key stroke in my window and programatically send it on to another preselected application. Is that the idea? If so, why would you need to do that?
Yes this is the idea as I told before. But dont think that the applications are limited. For example, you application can send a set of keys many times, by this way, you dont have to do it your self.
Also, you cannot do whatever you want using WM_CHAR and WM_KEYDOWN messages. If you use keystrokes, you can simulate anything that you can do with your keyboard. However, as far as I know, you cannot send keys like Alt+F4, or Ctrl+Alt+Shift+A using WM_KEYDOWN or WM_CHAR messages.
Moreover, while sending keystrokes, new dialogs may appear and if you use WM_KEYDOWN and WM_CHAR, you always should take care of this. However, if you just send keystrokes, when a new dialog/window appear as a result of the previous keystrokes, this new dialog/window will get the inputs.
Lastly, IMHO, using my class is much esaier than sending WM_KEYDOWN messages
Anyway, this does not mean that everybody needs this. But some people surely needs it.
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|