dc740 / AutoHotPy

AutoHotKey replacement using Incerception driver
GNU Lesser General Public License v3.0
59 stars 23 forks source link

Activate Macro Without Key #6

Closed lekary closed 5 years ago

lekary commented 5 years ago

Hey. How can I call a function with a macro without pressing a key? I experimented quite a lot with the code, and everything was not crowned with success. I would be grateful for the help.

dc740 commented 5 years ago

Hi. Remember that macros and saved macros are always python code. There is no intermediate representation or anything else going on. I recommend you save the macro to a file (check the existing examples) and then open the file to see the content. You will be able to create a function from that code. You can then call that function in any way you want.

Good luck

lekary commented 5 years ago

@dc740 This is a simplified code that gave me "Example7".

def recorded_macro1(autohotpy, event): autohotpy.moveMouseToPosition(639,520) time.sleep(0.1) if __name__=="__main__": auto = AutoHotPy() auto.registerForKeyDown(auto.F1,recorded_macro1) auto.registerExit(auto.F2,exitAutoHotKey) auto.start()

I could not call him in the usual way. recorded_macro1(argument1, argument2)

I do not understand what argument should be in "recorded_macro1". I experimented with writing a different argument and in all cases IDLE said that the argument is not correct.

dc740 commented 5 years ago

Check your comment format. It seems to be broken.

The code looks self explanatory. Instead of calling the recorded_macro1... just use the autohotpy code ignoring everything else:

def recorded_macro1(autohotpy, event):
    autohotpy.moveMouseToPosition(639,520)
    time.sleep(0.1)

if __name__=="__main__":
    auto = AutoHotPy()
    auto.registerForKeyDown(auto.F1,recorded_macro1)
    auto.registerExit(auto.F2,exitAutoHotKey) auto.start()

So, if that's your code... I'd do a custom function like this:

from autohotpy import AutoHotPy

def my_custom_macro(autohotpy_instance):
    autohotpy_instance.moveMouseToPosition(639,520)
    time.sleep(0.1)

if __name__=="__main__":
    auto = AutoHotPy()
    my_custom_macro(auto)

I didn't test the code above, but you get the idea.

Good luck

lekary commented 5 years ago

I tried this code and it did not work.

As I understand it, the macro call works like this: The function is created where the argument is "autohotpy_instance"

def my_custom_macro(autohotpy_instanc )

then a function from the AutoHotPy () class is called, and moveMouseToPosition is a function of the AutoHotPy () class

autohotpy_instance.moveMouseToPosition(639,520) if __name__=="__main__": And then the variable "auto" assigns the class name AutoHotPy () auto = AutoHotPy()

Then, as far as I understand, the function my_custom_macro is called, where the variable "авто" is an argument. my_custom_macro(auto) To which the handler responds: AttributeError: 'AutoHotPy' object has no attribute 'interception'

And many more mistakes

I tried to do so:

    auto = AutoHotPy()
    my_custom_macro(auto.start)

The handler wrote that

my_custom_macro
    auto.moveMouseToPosition(639,520)
AttributeError: 'function' object has no attribute 'moveMouseToPosition'

Now I'm at a dead end. I looked at AutoHotPy.py, there moveMouseToPosition is

dc740 commented 5 years ago

Hi, yes, the code I wrote above is just an example. You cannot directly run the macro without autohotpy running! If you see the examples, the last command is always auto.start(), because it configures interception object in the AutoHotPy instance and also enters loop to process the key presses (among other details).

If you want to leave AutoHotPy running, and also your code, you need to use python threading support. That is a topic completely outside of the library implementation. I haven't tried it myself but it should be fairly simple, assuming you are comfortable with threads.

lekary commented 5 years ago

Thanks, now I know where to go. Unfortunately, I am new to threads.

As I understand this cycle runs the macro.

In class AutoHotPy(object): and function def start(self): But this code is too complex for me.

while (self.running):
            device = self.interception.interception_wait(self.context)
#            print("#####DEVICE ID:"+str(device))
            if (self.interception.interception_receive(self.context, device, ctypes.byref(stroke), 1) > 0):
                if (self.interception.interception_is_keyboard(device)):
                    kb_event=ctypes.cast(stroke, ctypes.POINTER(InterceptionKeyStroke)).contents
                    if (self.recording_macro & self.enable_kb_macro):
                        self.last_macro.append((time.time(), copy.deepcopy(kb_event)))
                    current_key = self.get_key_id(kb_event.code,kb_event.state)
                    current_state = self.keyboard_state[current_key] #current state for the key
                    self.keyboard_state[current_key] = kb_event.state
                    if (kb_event.state & InterceptionKeyState.INTERCEPTION_KEY_UP): #up
                        user_function = self.keyboard_handler_up[current_key]
                    else:# down
                        if (current_state == kb_event.state):
                            user_function = self.keyboard_handler_hold[current_key]
                        else:
                            user_function = self.keyboard_handler_down[current_key]

                    if (user_function):
                        self.kb_queue.put(Task(self,user_function,copy.deepcopy(kb_event)))
                    else:
                        self.interception.interception_send(self.context, device, ctypes.byref(stroke), 1)

                elif (self.interception.interception_is_mouse(device)):
                    mouse_event=ctypes.cast(stroke, ctypes.POINTER(InterceptionMouseStroke)).contents
                    if (self.recording_macro & self.enable_mouse_macro):
                        self.last_macro.append((time.time(), copy.deepcopy(mouse_event)))
                    if (mouse_event.state != InterceptionMouseState.INTERCEPTION_MOUSE_MOVE):
                        current_state_changed = self.__toggleMouseState(mouse_event)
                        if (current_state_changed):
                            user_function = self.mouse_handler[mouse_event.state]
                        else:
                            #TODO: implement something to make a fake on hold. Mouse clicks don't automatically resend events like keyboard keys do
                            user_function = self.mouse_handler_hold[mouse_event.state]
                    else:
                        user_function = self.mouse_move_handler
                    #print("Stroke state:" + str(hex(mouse_event.state)))
                    #print("Stroke flags:" + str(hex(mouse_event.flags)))
                    #print("Stroke information:" + str(hex(mouse_event.information)))
                    #print("Stroke rolling:" + str(hex(mouse_event.rolling)))
                    #print("Stroke x:" + str(hex(mouse_event.x)))
                    #print("Stroke y:" + str(hex(mouse_event.y)))
                    #print("position 1:" +str(win32gui.GetCursorPos()))
                    if (user_function):
                        self.mouse_queue.put(Task(self,user_function,copy.deepcopy(mouse_event)))
                    else:
                        self.interception.interception_send(self.context, device, ctypes.byref(stroke), 1)
            if self.loopingCall != None:
                self.loopingCall(self)             
        self.macro_queue.join()
        self.kb_queue.join()
        self.mouse_queue.join()
        self.interception.interception_destroy_context(self.context)

Good luck

dc740 commented 5 years ago

Don't worry about that code for now. Take a tutorial and read the documentation on python threads. You will need to run your code in one thread, and the autohotpy start function in another thread. Also... from your code and thread, wait a second so the autohotpy start method has time to enter the internal loop before your code tries to use it.

Don't feel overwhelmed about multithreading. It can be a challenging topic and it's often the cause of many hard to reproduce bugs. You just need a lot of patience. good luck