v2.1: Implemented callback for SendMessage #330
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This pull request implements the use of a callback function with SendMessage to get the result asynchronously. This is done with the use of SendMessageCallback in PostSendMessage in addition to SendMessageTimeout.
The user defined callback function (hereby referred to as aFunc) is passed via the timeout argument. This is safe to use because SendMessageCallback doesn't use a timeout, and the previous version of SendMessage didn't allow non-integer types for the timeout argument. Thus this change should be backwards-compatible.
Because aTimeout is now of type ExprTokenType not optl, TypeErrors are not automatically thrown any more for invalid argument types. I opted to default to the 5000ms timeout in case of strings and floats, but additional checks for them could be implemented.
SendMessageCallbackProc is used as an interim callback function that is passed into SendMessageCallback, and the pointer to aFunc is passed via the dwData argument. SendMessageCallbackProc is used because I couldn't figure out how to use aFunc directly with SendMessageCallback, if it even is possible. The loss of the dwData argument isn't important for the user, because it's trivial to replace using a BoundFunc.
Alternatively I considered using CallbackCreate and returning the created pointer with the SendMessage call, but that would require the user to explicitly use CallbackFree inside the callback function. That would be less convenient than the implementation proposed in this PR.
This implementation uses
aFunc->AddRef();
and releases in SendMessageCallbackProc. This theoretically creates a possibility for a memory leak if the callback function is never called, but that risk should be negligible if the SendMessageCallback call is successful. Alternatively the obligation to keep aFunc alive could be passed to the user instead, but I couldn't figure out how to do that.Example
Receiver.ahk
Sender.ahk
I'm not quite sure how useful this addition would even be though, because SendMessageCallback can also be rather easily used via a DllCall (
DllCall("SendMessageCallback", "ptr", receiverHwnd, "uint", MsgNum, "ptr", 123, "ptr", -456, "ptr", CallbackCreate(SendMessageCallback), "ptr", 0)
), which compared to this PR is only marginally harder to use and necessitates the additional use of CallbackFree. Since I would consider using SendMessage with a callback an advanced technique and advanced users should know how to use a simple DllCall anyway, then implementing this PR may not be worth it? Although the same could be said for the regular SendMessage...