From: Rich007 on 8 Oct 2009 19:23 D'oh! DO EVENTS!!!!!! If I include Do Events after the Call MySendKeys line it works. Thanks for your time Karl. You and the other experts on here are great! Cheers Rich "Rich007" wrote: > Thanks so much Karl, > I can now get the code to run using either Call MySendKeys("{ENTER}") or > Call MySendKeys("{~}"). > > However, I have noticed a very strange situation. Let me give you the > background (but if you are short of time, just jump to the very end of this > post). > > I have a macro called "OnReturn" which is bound to the return key, i.e. it > runs everytime the return key is pressed. It is assigned in design time via > a macro called "AssignReturnKey", using the code" > KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyReturn), KeyCategory:= _ > wdKeyCategoryMacro, Command:="OnReturn" > > All of these macros live in a global addin. > > Now the OnReturn macro needs to do some stuff, then perform the return > keystroke as if the return key had never been assigned to a macro at all. To > do this, I came up with the following code for OnReturn: > > Sub OnReturn() > 'DO OTHER STUFF HERE... > UnAssignReturnKey > Call MySendKeys("{ENTER}", True) > AssignReturnKey > End Sub > > The logic is this; first unassign the return key via a macro that runs the > line: > KeyBindings.Key(KeyCode:=BuildKeyCode(wdKeyReturn)).Clear > to unassign the return key binding. > > Second, this is where I need to perform the unadulterated Return key-stroke. > > Third, I reassign the key-binding using the AssignReturnKey macro that was > run during design time. > > Both AssignReturnKey and UnassignReturnKey macros have code to catch errors > which is why I haven't included the full code for now. > > So I have tried using various different methods for calling the "pure" > return key-stroke ( Selection.TypeParagraph or SendKeys "~", True ) > and these worked ok, but I was looking for a bullet-proof way that would work > for all international key-boards and language settings. > > Now when I use your MySendKeys("{ENTER}") the code jumps into a loop. It > hangs until I either click the mouse or press a keyboard button. If I hit > one of the extended keys, the Enter "executes" in combination with that > extended key. So the code hangs, until say I hit Ctrl, then I get a > pagebreak! > > What I think is happening here is that when I hit Enter, the OnReturn macro > fires, this calls the UnAssignReturnKey macro to clear the keybinding, then > the MySendKeys("{ENTER}") is called which effectively re-hits the return key > and this then tries to run the OnReturn macro! This is my theory, I have no > way to prove it yet, but the MySendKeys("{ENTER}") shouldn't call OnReturn, > since the key was unbound in the previous line of code. Could there be some > kind of lag? The strangest thing is that if you replace the line: > Call MySendKeys("{ENTER}", True) > in OnReturn, with just: > SendKeys "~", True > (so using the original SendKeys rather than the API version) it works > perfectly! > > Any ideas why the MySendKeys macro doesn't recognise that the return key has > just been unbound? Thanks again (especially if you've read this far!). > > Cheers > Rich > PS. Having re-read that I can see this could be quite confusing, so here is > the full code that I think is runable (if you have the MSendInput.bas > imported from your site): > > Sub AssignReturnKey() > 'Assigns a macro to intercept the Return key > ' > Dim AddinPath As String > > AddinPath = AddIns("test.dot").Path > CustomizationContext = Templates(AddinPath & "\test.dot") > KeyBindings.Add KeyCode:=BuildKeyCode(wdKeyReturn), KeyCategory:= _ > wdKeyCategoryMacro, Command:="OnReturn" > End Sub > > Sub UnAssignReturnKey() > 'Clears any assignment to the Return key > ' > Dim lngCode As Long > Dim kbLoop As KeyBinding > Dim KeyInUSe As Boolean > Dim AddinPath As String > > AddinPath = AddIns("test.dot").Path > CustomizationContext = Templates(AddinPath & "\test.dot") > > lngCode = BuildKeyCode(wdKeyReturn) > For Each kbLoop In KeyBindings > If lngCode = kbLoop.KeyCode Then > KeyInUSe = True > End If > Next kbLoop > > If KeyInUSe = True Then > KeyBindings.Key(KeyCode:=BuildKeyCode(wdKeyReturn)).Clear > Else > MsgBox "The Return key was not bound!" > End If > End Sub > > Sub OnReturn() > UnAssignReturnKey > MsgBox "Hello" 'Will show repeatedly - Ctrl+Break to exit > Call MySendKeys("{ENTER}", True) > AssignReturnKey > End Sub > > > PPS. What setting should I have for the Const VBA = True/False line? I had > to set it to True to get it to run (otherwise there are undeclared varibales). > > PPPS. OK, had a thought an I think I have some more evidence to bring to the > table (please bear with me!). On your website, you say "My routine accepts, > but ignores, [the wait] parameter". Well that would explain it. If my > OnReturn code continues to run, the return key is reassigned before the API > code has done it's stuff, so by the time the API code performs the return > key-stroke, the key has been reassigned and the OnReturn code runs again! > Did you ever figure out how to make your code WAIT before continuing?
From: Karl E. Peterson on 8 Oct 2009 20:23 Rich007 wrote: > D'oh! DO EVENTS!!!!!! > If I include Do Events after the Call MySendKeys line it works. :-) > Thanks for your time Karl. You and the other experts on here are great! I'm glad you got going, but wanted to comment on a couple of your other points... >> PPS. What setting should I have for the Const VBA = True/False line? I had >> to set it to True to get it to run (otherwise there are undeclared varibales). Set it to True if you're running in VBA, False if you're using VB5/6. >> PPPS. OK, had a thought an I think I have some more evidence to bring to the >> table (please bear with me!). On your website, you say "My routine accepts, >> but ignores, [the wait] parameter". Well that would explain it. If my >> OnReturn code continues to run, the return key is reassigned before the API >> code has done it's stuff, so by the time the API code performs the return >> key-stroke, the key has been reassigned and the OnReturn code runs again! >> Did you ever figure out how to make your code WAIT before continuing? Sounds like what you're saying is the OnReturn routine is re-entering itself? That's a natural hazard in an event-based programming model, when you're twidding the user-interface with code. You can avoid that problem "very simply" by setting a static flag within the routine, to prevent re-entrancy... Sub PotentiallyReentrant() Static Busy As Boolean If Not Busy Then Busy = True ' Do the work that potentially triggers a re-entry. Busy = False End If End Sub Make sense? -- ..NET: It's About Trust! http://vfred.mvps.org
First
|
Prev
|
Pages: 1 2 Prev: Extracting Footnotes and Endnotes Next: Print Preview Doesn't Trigger BeforePrint Event |