I've seen a few posts with other people having the need to do this, but no good solutions. Here is the solution I found that works really well for me.
The problem:
Need to handle something COM-side, for which the only available Hook that catches the event is the Refresh Display COM hook. Since the hook can't call itself, anything you change from this hook doesn't appear on the screen until another user-interaction. Say you have an audit function that catches an invalid change to an item (due to a business rule). You can delete, or revert the change, but nothing is shown on the screen until the next user-triggered Refresh Display. This works, but would look very confusing to the user.
Here's a better way.
1. Create a COM add-in that triggers on the Refresh Display Hook
2. Within that, check your business rule and make any appropriate adjustments to the transaction, etc.
3. Set a Variable. Make sure it's one that is not used elsewhere in your code.
mySession.Variable(6) = "RefreshDisplay"
4. Add the HTML status window to top of RMS screen
5. From that window, create a JS loop that checks for a change to the Variable
6. If found, call the QSBridge version of Refresh Display (qsBridge.FireEvent("RefreshDisplay"). Viola, screen is refreshed, and your change is immediately evident w/o any further user interaction required.
It's a roundabout way, but looks seamless to the user.
Here's code for the status window:
<html> <head> <object classid="clsid:44C4C3AC-D0F1-11D2-919D-006008C88FC3" height="0" id="qsBridge" style="LEFT: 0px TOP: 0px" width="0"> <param name="_ExtentX" value="26"> <param name="_ExtentY" value="26"> </object> </head> <script type="text/javascript"> <!-- var timerId = 0; var qsRules; function getRules() { if (!qsRules) qsRules = qsBridge.RequestQSRules(); return qsRules; } function checkForCommandFromCOM() { try { var rules = getRules(); if (rules) { var v = rules.Session.Variable(6); if (v && v !== "") { switch (v) { case "RefreshDisplay": qsBridge.FireEvent(v); break; } rules.Session.Variable(6) = ""; } } } catch (e) { if (timerId) clearInterval(timerId); } } function init() { timerId = setInterval(function () { checkForCommandFromCOM(); }, 500); } //--> </script> <body onload="init()"> </body> </html>
*This post is locked for comments
in a com object hook use send {{ENTER}} and " " (a space) that will do the trick
@Ed - I was using SendKey, to no effect (doesn't register until separate user interaction). Have not tried using user32.dll, interesting idea. Are you using this from within the RefreshDisplay hook?
I always just sent a keystroke to the application using sendkey. Also made sure that the window was active by finding and activating via user32.dll
//Import the FindWindow API to find our window
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindowNative(string className, string windowName);
//Import the SetForeground API to activate it
[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
private static extern IntPtr SetForegroundWindowNative(IntPtr hWnd);
Stay up to date on forum activity by subscribing. You can also customize your in-app and email Notification settings across all subscriptions.
André Arnaud de Cal... 290,802 Super User 2024 Season 2
Martin Dráb 229,133 Most Valuable Professional
nmaenpaa 101,154