ControlSend() works in a similar way to Send() but it can send key strokes directly to a window/control, rather than just to the active window. It takes the window/control hwnd as a parameter with keystrokes.
I have used
SendMessage($_,WM_KEYDOWN, VK_RETURN, 0);
SendMessage($_,WM_KEYUP, VK_RETURN, 0);
and
SendMessage($Ctrls5,WM_CHAR, VK_RETURN, 0);
I have also used SendKeys("{ENTER}"); but it wants the window to be present in foreground.
Help me in solving this.
If you are sending the Enter key for carriage return in text box then you have no function for that.
But if you want to send enter key on a button or any other control(to click on it) then you can do so by the function
PushChildById(Parent_HWND ,ctrl_Hwnd);
PushChildButton(Parent_HWND , Ctrl_regex);
Related
I want to create a Delphi application that does something interesting when the user moves his mouse over the top-left corner of the screen. I thought about it and plan to do it with the following strategy:
Create a very small 3x3 Form and make it transparent and always on top. Also make it with no title bar or border.
Define mouse enter event for the Form.
I use the following code for step 1:
procedure TopLeftForm.FormCreate(Sender: TObject);
begin
FormStyle := fsStayOnTop;
self.TransparentColor := true;
self.TransparentColorValue := self.Color;
self.BorderStyle := bsNone;
end;
The problem is that I found that when the Form is transparent, it can't capture mouse enter events. I could make the Form not transparent in order to get mouse enter events, but that way users can see the Form at the top-left screen corner, which is not what I want.
What's your suggestions to my problem?
What you want is a 'Hook' that can give you information about mouse events without the events being intended for your program. It's too big a topic to be able to give you a how-to in one go, but these two links should be helpful:
Understanding how to use Windows Hooks
Mouse Hook Tutorial with Delphi codes
Why use a Windows Hook?
The Windows environment is designed around messages being passed around. Typically, a program is only interested in messages that are sent directly to its own windows. Trying to make sure that your application has a window that will get the messages blocks other applications from receiving those messages when they are in the same location under yours, and if another window is over yours then you won't get the messages. If you want to know about activity that's happening that wouldn't normally be sent to you - for example, a mouse click outside of your application's window. To enable applications to have visibility of events that are not destined for itself, a windows hook can be used.
There are different types of hooks, depending on what you want to access. A mouse hook is appropriate for what you have specified here. The system maintains a 'Hook Chain' for all of the hooks that have been installed - it will be your responsibility to pass the messages on down the chain, and to uninstall yourself from the chain.
To access the messages, your hook function will look something like this (code taken from the 2nd link above and adapted):
function MouseHookHandler(ACode: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
var
vMouseInfo: PMouseHookStruct;
begin
if ACode < 0 then
Result := CallNextHookEx(Data^.MouseHook, ACode, WParam, LParam)
else
begin
vMouseInfo := PMouseHookStruct(Pointer(LParam));
PostMessage(Data^.AppHandle, WM_CUSTOM_MOUSE, vMouseInfo^.pt.X, vMouseInfo^.pt.Y);
// we dont want to block the mouse messages
Result := CallNextHookEx(nil, ACode, WParam, LParam);
end;
end;
In your hook function:
ACode is dependent on the type of hook and indicates the event
wParam and lParam have a meaning specific to the event
To pass the message on, you should call CallNextHookEx - however for some hooks, the message will always be passed on regardless.
Hooks can be installed as Global hooks - meaning they intercept messages on all threads running in the same Desktop / WinStation as the calling thread. So, if you have multiple users connected via RD, for example, the hook is specific to one of those desktops only.
What I need is to map my keys from external numpad to keys on my keyboard. I've decided to use the AutoHotInterception program from evilC. The overall goal is to be able to use windows mouse keys with my keyboard. I have come to the point where program registers both inputs from my numpad and keyboard and I can type numbers with my keyboard but it doesn't really affect the windows mouse keys.
This is what I have so far:
#SingleInstance force
#Persistent
#include Lib\AutoHotInterception.ahk
AHI := new AutoHotInterception()
keyboardId := AHI.GetKeyboardId(0x04D9, 0x8008)
numPadId := AHI.GetKeyboardId(0x0C45, 0x7663)
AHI.SubscribeKeyboard(numPadId, true, Func("KeyEvent"))
AHI.SubscribeKeyboard(keyboardId, true, Func("KeyEvent"))
return
KeyEvent(code, state){
ToolTip % "Keyboard Key - Code: " code ", State: " state
if (state) & (code=30)
{
Send, {NumpadUp}
}
}
^Esc::
ExitApp
The main problem is that you need to send input at hardware driver level to trigger WMK.
Then I'd like to say that your questions seems quite weird. It seems to contradict itself?
You want to remap keys from the external keyboard, but then you also say that you just want to use the numpad with your main keyboard? So what is the external keyboard for actually?
In any case, Here's some advise and a revised script you can probably adapt for your own use. So firstly there's really no need to subscribe to the whole keyboard. Just subscribe to the keys you want.
And since I'm quite unclear on what it is you're actually trying to do, I'll just show an example of how you'd remap A, S and D to Numpad1, Numpad2 and Numpad3 at hardware driver level.
#include Lib\AutoHotInterception.ahk
AHI := new AutoHotInterception()
;kind of optional
;if you don't switch up stuff, you'll always have the same id
keyboardId := AHI.GetKeyboardId(..., ...)
;binding arguments to the function object to make use of the same function over and over
;so don't need to define a new function for each key
AHI.SubscribeKey(keyboardId, GetKeySC("a"), true, Func("KeyEvent").Bind(GetKeySC("numpad1")))
AHI.SubscribeKey(keyboardId, GetKeySC("s"), true, Func("KeyEvent").Bind(GetKeySC("numpad2")))
AHI.SubscribeKey(keyboardId, GetKeySC("d"), true, Func("KeyEvent").Bind(GetKeySC("numpad3")))
return
;the key argument will be the argument we bound to the function object above
;the AHI library takes care of passing in the state argument
KeyEvent(key, state)
{
global keyboardId
AHI.SendKeyEvent(keyboardId, key, state)
}
^Esc::ExitApp
Sending input is documented here here.
(Side question, any chance you're doing this for OSRS?)
I'm linking an arcade button connected to a USB encoder with a Max patch. The button is behaving strangely. Here's what happens:
I have the button mapped to the a key. When Max is open, this functionality breaks. Even outside of Max. Even once I close Max, I need to remap the key. I'm not using MAME or anything like that; just JoytoKey for the mapping.
This issue is negated partially through use of the HIobject. Max recognizes the button and I can use it, however it's not functioning as an on/off. Rather a bang is sent on button press and release. How do I make the button work normally (send a single bang on press, and none on release)?
Here's my patch, if it helps. I don't know how useful it is without my video files:
<pre><code>
----------begin_max5_patcher----------
2245.3oc6cszbjpaEdsmpl+CTr1gB8hGYY1jJYaRVMUptvzx1ZtzPGdX6I2J
+2i3YyCoF0.M8hqbMi6FjP5b9zQe5bPvw+92+1Sluj7EMyz3Oa7Cimd524m4
opyUdlmZOwSlmB9JLJHqphlEmnwElO2TzGAowAmnBJIt3DKNhlWcUf1ydNHk
W8bZ5AZbvKQzAExxomp6j+JMllxBMLL9W+i+hgweO4WY4rveyvneymTj219n
tl3X00m7xO+S.+tJWWy7eclVqqlr3bymMLq9uw+9hvkG9NK9sCozv75Zhv9V
DhM+G.B.P1Pf+yF.Hwxl+gKn7CHzx9RajE7A83gf77T1KE4zKeKqATaQ0RrK
pfl7Z646JnOJEkD+lX.dP0NwGhJqhsnBydOIMWgFge9SM3ib7uSSGbosPKro
r+22+V82Z+Rym7OdVYKsSzrrf2ncih4zuxaJPlcFTr4APj4AQt4wBrIbsKsE
P9WrHVrdGS+jKfSU62YyL4ZnRCEnzH45bDKKegyG78rP9k+f7g1HnC.xw.d8
taHwOY4VexhOl7ow4nfeUJ5GYYm6p34TZFMNOHmkDeHhESCSJhyGPTLnJWzO
Hvxydj5g8qFacvk+lX2e19MMNzuKkZUBskOD8RP7ayODAvdkPuCeTojjBh1.
SxH1GTqJ3WDw+zRkft.WGqJCEWaWejKDa6H15AWg0.Rer9TxQZeNNy7zf3LV
KZBWwBOqY.C3cEdj4GrVChbOWqYxXpv0a.yudy0andq4vEQPIfw+DtmKyHij
IiFYPlyhF54Nkv.BpWL.O08.UVs5lr+bwqkuPUU3t.v9lKBY5C.j0B.XfqkM
4AA.dqG.bVK.f7.ON.vctoXBc4XWmh4tZ.VQU3t.vNyBv.eKzCkCya0.rhpv
1GKh+pCDg3uz.Qv1tUNYSpiCcK73Vpd5sd8zcwAbwcRxdmzSEni.R.8EAPpL
+frhPUw6lEhB7L1RFFueHGZwHG.sa1by6koqmkCtLJAOO9uID281BDrTbDx8
sPEQ+drz2rgix65p.sFHaMVoKDVuoE9vvUGruhpvcwyB7r1sDQC96nmEXvpi
NRQU3t.vnYAX.4ACvq91UopJbW.X3rTDdXKviDfQ9qlhPQU3t.vfYAXBxxy+
QBvqN3CUUgECvuFkTdaxl8lq5VuqTv16S8UwtqdmQ6tGquljdJnpCb1Brlb8
6UZEdOy8KUlRt4luoAwGSNY.rUE3qcpwwYYFs2j+XH702aSkvvox616Z67tH
fcEvNsit1hVtqsbyOv8z0Von5B8KXGQU3huoFPf28MfAon5BcFXOQ0EeKT.d
tOHa0E5Avdhp3EipDGkD8Eipkazc6NbO+xPB16ZTIWe0ONDhCAX6iJcJoZqg
Qd27dYitosF8JVqbE6.2whT1WsOGNGYgkMVP5uVf2VXazT0j.br7KOGDh4.B
1Ai4CHt98U5njDtpbNIMefVbLHOXxdnFFwN28vRMXSTexL3krjnhbJWfeuB.
9aw4oIG9mexdKH8TFz5TxGW1.TteUrHZ2VjpPc+MVbMvxKiQKOS+ZTpEC2NV
tzlDmyGgNjwGjnc66aegtZX4bQd6Fqyw1da6ZcwGZER9XVgK101FgvXyg06H
qYObAOOtIJoAJRoCZFDFU0LvQMSoVPqUyeXXOpKRC9LOYxjxdZwgltR3kmy3
7SgAQMk5XOp7ORhZz.qQkTjQOlkew7arbMnrmK+2TPnTwNmv8KK6PFMrwDpx
0U6wcWvwfy4BGLRaFFEHiGKR6lHNQBOmb4Yj3GS6vRjYnTMr7vjHdH.cVHlA
ou8h4zlPXW+ZYfEWlcMo7vfv24cN6+1d4Vf5Iw17kprA.GAh5oLgMUPQdBmO
gEJsT97fTwHKeHNKMT5PbQL6+THQAOKC13C1zzyBundVCcJyyBgttmZoqzFx
ZfgDaBafdHxnRGBGRrpuvDIbVIM9MVbmUyGuZ1rL3fmaitkCmiNkUQQVdHkO
Hec5TEpqlNUSmpoS0zoZ5zRJRvMPmBzzoZ5TMcplNUSmNlNMHH8LRApTo0SS
ipoQ0znZZTMMJTQZTcv8ZZTMMplFUSiJjFEnHMpNndMMplFUSipoQmPi1tq7
pPkd05poS0zoZ5TMc5eToSG9PNYftgmHJC8cKUSnpIT0DpZBUo6gO5F1CeMc
plNUSmpoS+CCcZaASSSX0snYYNBbbdPs5cOHpoG58BZjkTjF11sco.tdJn4Q
ZVNKt2Dlt2YOiq9xfndORTpC2t9yUk9qJ2EtU8nuYeygqqgcYHP1w9lrXDYZ
ZsBPpRQmHjS86.Y+i7qR4GnxyMIEWhr1FEChUBJcuplAbbDj0GpyRN.Gjjx1
F42cKjeemouien5zroP4uprsQ982.4GB8l91zsOxORIweLizH4WnINe5a06s
FBTm2P6ejWc1mzywBONYUVVzkNJI8HMsxQwMRWmkC.3uYjNpgsiLf5zX6sPB
.ag0Iez8AM6BoD6FhrcCYpsRnmjwLu8SDjY13tah.1VhH3reh.PhHP1OQ.JQ
D72MQvEKQDv6mHPtmrXpIBNRDAv9IBtRDA39IBxnlPagHnTfIvsKvDjRdWAm
y6PjfL.QclzQnmiUksIx+XJRIxu+LdGRDjqEZyDPdRJaajek7eXrWFikeGfb
4WjuEan7CuECVY1ObeVmlUFvMQGIJxI7VEcDYS7eyG7nhtff1.4GAgV6mDS1
BIlfq+q2wtHwaQDzHOxNhwaQLyUYY88RhcUJNDxL7f9tBRpzM7f90I4kgGUy
wHb961ww3pjEO45qQggNBxH40ZSyH0nip0s9GsMZiiRZyLyF3FNxzFT88tXz
Q0ZSyrnMTaTZt8XNKUt6LsxO4h1rMRrRtHRPyv36I3OgDMRLr+Lk1iZv+5UJ
Di+M2Z9fym+fll0HO0Jh4ofelTG.+y0GyhqOtNwEZlR+f0dI0ItPyfzv2Y4z
v1cvy7Kml79T0eYYRiKXsAeTBkkccUdXpbeEyNGTCZU4qou+MdE9+qypUK.
-----------end_max5_patcher-----------
</code></pre>
It's hard to give an exact answer without knowing what your USB device outputs, however in your patch whatever exits the [hi] object goes into the [live.text] button, which is set to Button mode, always converting it to a bang.
In the patch below I set the [live.text] button to Toggle mode. I also took the liberty of cleaning some other things up.
The next thing though is that you will need to find out what part of the output of the hi object is the information you are looking for. You can do that with a [print] object. Then you can select that number with an [unpack] and select the 1's and use that to trigger [random] (see the patch below).
----------begin_max5_patcher----------
1559.3oc6Z0ziiZCF9bxuBDmmF4O3ypdpWpZu11SqVE4P7Lw6BXpwjYFsZ+u
WaCjPBDvIgY6glLRCAaiseedd+zjusbg6F9azRWme14SNKV7skKVXZR2vhl6
W3lQdKIkTZFlaBOKilKceptOI8Moo8ew4YV9VG4NpSdU1FpvgkatKkUJUegH
cJekIS1QKc1PkuRo4N.Gh5QfsyUgfVplZhjwyWmxxoI7pbyriZFgZlY4oToY
q.aZjs0rA3a9xOAAtGGIuR1NTP6JPTa.V9KqEzDYsTiBvq.O4.AlKXXj9BBr
B37Y8y78kK0+6IKQmb5qp8QOvoPvNBYSIDwWuLfTadef5CDCgX.BFeThPFAB
MuBTUdAI4qJBT8msxUzvxEto05ljuWPqEJWCjcxEmOeYL.FFrJV+IDDFiCQd
f.EFfhWgMshiQ.LJ.hdxIL7tPjKa.jriyKo055M1.6nBps3S3Mq6hA8kRTTv
GglbIM8nA6IRDpuD4MrDgtDiugj+hlqGknQ.+AH5HCoh89HT1kNrAcQ0U4CZ
V3HCenT57a2EVx8ngQJ3.Ka21GzlYbvynUfqAJX7GCbAsDt7CuQ3B9CFt.Gz
qtC3pR41npciumHxIYz9cvjzr5w+azbpfk33372+4u537G72KkLkSWGacn.O
DIofHTKljJVSyIaRocefqya7jlmP.nu4oxAkVcqg16xzkj8zsqIRofsoRRO9
sxFjrAJ0HVZEk+bayssepvUk0rcA5MJ7vN8jgkxyeYPv+jQkoHuN3zI8UtiK
jSOEsvGptKi9R6kqT4IiVVRdg1yXqqpyTtig9ia1ziyG21P48v+7jNB75GIB
+g3kYGyVy.7UFERmv5zp4CktwPReWuaymz+Elb0qp7s4u5TjRdWuk2xJKlNS
Z73dlQvUQfy3TuXi0afwGnW703lFAFG6s1QskYFX7VG3aT3fH7co2kx1SWY.
7AbY2qyKFoa.0j3n9pId0Aj8uFzEFYi+cofjWxZQXz7vG2XVZCYfLfj+QETP
MZndmqthrHzv4j7MFdXzoYFCQLRF6.6Kw9RJxJ6HC0EFEo9uuen1qFDbLAN7
E0cGpx.z+ANFPgAyPQBOqzQTZTSY2GVmwiIkQePu7ddlKxHlAGXaXL+wr1Ay
mcsARsAN8vmKbymVqxo0VdlCDXIP6aRsLHnGPOklH16GasDHsmtS2o2.poi+
2F32hhs5ESGqgMym.e+.eHHFqMLLG9ENBzA+R47htxs9dAsP4f6rhHFOVU30
q7hmfA1JHuJ4lkv8RjhBmVqryDr2ZKdYKKQOQDw6GYK0iUTIWqU9pDzoNzkl
ZBCF.A8gpv851PHOEV6E34oc6zMmosDI47nXIorhCGBa2vXKbIaJ4opHepMx
Nin964RAe8e8J6EhHqDsJiu+PbEkaEVJ8PfmoG5WUoPVWFAeOipaoy.ZnuJP
jNKe+Pbm9NSqvHD7bohlVWpXJ5g.xcjktLV2hKpCjySaTWOhUlNDMyV+dR3o
Jmn7ssbMQ7xlSmzpb1+T0z8oOqxXkJJNzSaGMgeasDmfJXF7UeKUUX9nTwzC
0JpHvSqc4G8fJFkJf1SEvakJhBLTQ7CpXPpfPDE3oogKMLqn.jef18K3AEbQ
J.YGEbyNj7hMT.7AEbQJ.ZGEbyNhv.sin.zCJXPJnM8GKngwFpcwDPFqA7Cp
XzjVcv1m0pyMGcvGqq5Iv6AYLZtRX6yU5lohvProNo+eQEMMdxY4YlBW8Auc
1O5FSgl51Osn+RdkHoc607xLb5TLIsTxxOTY7mN7CHoyX3hsTgol1AOmAaW3
H0jBmXgMmHsykNQi4TDiFVDg20B6YwBi8lAI7.NM5RMGqDxh0Qe1L28BoOP2
I0OPyA1YgDglKAZRnaNT28sQWXNDIrUJ39yjI7jNKN0MUFaaAW4TswuHLdnW
bVP+WeTj+pPuabb0+9WfPvJu3A55d0Tis.EvygIQnMpp52E68uT1nr1WlpC6
QJJ1SEkMC1rFtYjuvMttidxbKKu9VyAv5Jn6YsiutEhHYGSRSZOnV22BpO.e
WcbbQdEqINfR5VpOYURYoNclxBRsfXNX8kee4+Jwi4ZG
-----------end_max5_patcher-----------
I'm trying to detect if ffdshow is currently running on the computer using AutoHotKey.
Someone has suggested that I can achieve this by sending a message to the to the ffdshow window handle. If it succeeds, then ffdshow is running.
According to ffdshow, the window handle is 32786 and, according to the AutoHotKey documentation, I want to use PostMessage and then check ErrorLevel.
However at that point, I'm struggling to understand the documentation. I've got the following:
ControlHwnd := 32786
VarContainingID := 32786
PostMessage, 0x00, , , ,ahk_id %ControlHwnd%, ahk_id %VarContainingID%
MsgBox %ErrorLevel%
but that always reports a 1 indicating that it was unable to connect to the window handle - even though ffdshow is running.
I've also tried changing PostMessage to the blocking SendMessage but that always reports FAIL.
I'm clearly doing something wrong, but I'm not really sure what. Can anyone help?
Thanks to blackholyman and MCL, I found the problem.
After digging around in the sample code found here, it turns out there is a window class for ffdshow called ffdshow_remote_class.
As a result, the following code:
DetectHiddenWindows, On
WinGet, activeid, ID, ahk_class ffdshow_remote_class
MsgBox activeid = %activeid%
will return a hWnd value for ffdshow (stored in activeid) if it is running or nothing if it is not.
1-The code below displays the properties of the pressed key.Try it by pressing a key and observe the results.
figure('Name','Press keys to put event data in Command Window',...
'KeyPressFcn',#(obj,evt)disp(evt));
you will see outputs like this( e.g upon pressing space bar)
Character: ' '
Modifier: {1x0 cell}
Key: 'space'
2-Now simply add the following line of code to above ( or simply execute it before clearing the workspace)
cameratoolbar('SetMode','orbit');
Now press any key and nothing happens! the control will no longer be transferred to your costume call back function! ( here:#(obj,evt)disp(evt)).
same thing happens for WindowButtonDownFcn, WindowButtonUpFcn too.
How can I get around this? I wanna be able to handle KeyPressFcn or WindowButtonDownFcn after executing cameratoolbar('SetMode','orbit').
I found the answer: Once the cameratoolbar('SetMode','orbit') is called one of these two happens:the handle to the figure is lost or the event handler gets its default value. I am not sure which one though. Therefore we can add the following code to re-assign the lost handler back to our own call back function:
set(gcf,'KeyPressFcn',#(obj,evt)disp(evt))