HQC - Hover Window Quick Click Widget (Win)

Moho allows users to write new tools and plugins. Discuss scripting ideas and problems here.

Moderators: Víctor Paredes, Belgarath, slowtiger

Post Reply
User avatar
570295535
Posts: 32
Joined: Sat Feb 04, 2023 9:32 am

HQC - Hover Window Quick Click Widget (Win)

Post by 570295535 »

:D I used to want to use @Greenlaw 's MQC, but I don't quite understand English. Later, I made this small tool.
There are English and Chinese versions available,
The function is to integrate commonly used shortcut keys into the floating panel, and the interface color scheme matches Moho.

Image

Name:HQC(Hover Window Quick Click)
Last update date:2023.10.14
Apply to the full range of Moho.

The code is 100% secure, and the source code is already included in the download link.

File Download(蓝奏云):
https://xsz.lanzouq.com/b00o34kob

Backup Download(dropbox):
https://www.dropbox.com/scl/fo/wvux7xwp ... zcj5j&dl=0
Last edited by 570295535 on Sat Jun 29, 2024 4:17 am, edited 6 times in total.
I'm from China, currently using: Moho 15 » Win10 System
:D :D :D :D :D :D :D :D :D :D :D
lyf1981
Posts: 1
Joined: Wed Apr 17, 2019 6:43 am

Re: HQC - Hover Window Quick Click Widget (Win)

Post by lyf1981 »

very good
User avatar
synthsin75
Posts: 10264
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: HQC - Hover Window Quick Click Widget (Win)

Post by synthsin75 »

I would be wary of running an exe from an unknown source. If this is written in AutoHotkey (like Greenlaw's MQC), you should share the source code.
Otherwise we have no idea if it could be malicious.
User avatar
570295535
Posts: 32
Joined: Sat Feb 04, 2023 9:32 am

Re: HQC - Hover Window Quick Click Widget (Win)

Post by 570295535 »

synthsin75 wrote: Fri Jun 28, 2024 3:01 am I would be wary of running an exe from an unknown source. If this is written in AutoHotkey (like Greenlaw's MQC), you should share the source code.
Otherwise we have no idea if it could be malicious.
It's not written by AutoHotkey, it's written directly in py. If you want to add malicious code, pay me $10 to help you join. :D
I'm from China, currently using: Moho 15 » Win10 System
:D :D :D :D :D :D :D :D :D :D :D
User avatar
synthsin75
Posts: 10264
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: HQC - Hover Window Quick Click Widget (Win)

Post by synthsin75 »

If it's in Python, you could still post the source code.

Otherwise, I advise people to not take the risk.
User avatar
570295535
Posts: 32
Joined: Sat Feb 04, 2023 9:32 am

Re: HQC - Hover Window Quick Click Widget (Win)

Post by 570295535 »

synthsin75 wrote: Fri Jun 28, 2024 11:28 pm If it's in Python, you could still post the source code.

Otherwise, I advise people to not take the risk.
Dude, you are really persistent. There are only a few of us on the forum, so there is no need for me to poison. I have already placed the source code for 20231024 in the original download link, or, you can look at the following code:

Code: Select all

import tkinter as tk #创建窗口依赖
from tkinter import messagebox #弹窗依赖
import time #延迟休眠依赖
import pickle #保存窗口位置依赖
import os #保存窗口位置依赖
import pygetwindow as gw #win获取其他窗口依赖库
import pyautogui #按键模拟依赖库

def set_button_font(widget): #设置所有按钮字体的大小、颜色、背景色
    #获取组件的类型
    widget_type = widget.winfo_class()
    #如果组件是一个按钮
    if widget_type == 'Button':
        #将字体配置为当前字体的新大小
        widget.configure(font=("Microsoft YaHei", 8), fg="#DFDFDF", bg="#3D3D3D") #字体大小、颜色、背景色
        if widget["text"] == "Back\nspace": #单独设置删除按钮背景色
            widget.configure(bg="#AB4040")
    #遍历组件的子组件
    for child in widget.winfo_children():
        set_button_font(child)

def active_window(): #激活窗口
    #寻找window_title的窗口
    target_window = gw.getWindowsWithTitle("- Moho")
    if target_window: #如果找到该窗口
        window = target_window[0]
        window.activate() #激活窗口(设为活动窗口)
        return True
    else: #没找到该窗口,则提示
        message = f"Please Run Moho before using!"
        messagebox.showerror("Tips", message)
        return False

def Copy_button_click(): #点击按钮_复制
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "c")
    #设置按钮颜色
    Copy.config(bg="#1E1E1E")
    Cut.config(bg="#3D3D3D")

def Paste_button_click(): #点击按钮_粘贴
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "v")
    #设置按钮颜色
    Copy.config(bg="#3D3D3D")
    Cut.config(bg="#3D3D3D")

def Undo_button_click(): #点击按钮_撤销
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "z")

def Cut_button_click(): #点击按钮_剪切
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "x")
    #设置按钮颜色
    Copy.config(bg="#3D3D3D")
    Cut.config(bg="#1E1E1E")

def FreezeKeys_button_click(): #点击按钮_冻结帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "f")

def Redo_button_click(): #点击按钮_重做
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "shift", "z")
        
def Backspace_button_click(): #点击按钮_删除
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("backspace")

def Save_button_click(): #点击按钮_保存
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "s")
    #获取按钮的原始文字
    old_text = Save.cget("text")
    #修改文字为 "OK",0.5秒后恢复为原始文字
    Save.config(text="OK", bg="#1E1E1E")
    Save.after(500, lambda: Save.config(text=old_text, bg="#3D3D3D"))

def Add1Frame_button_click(): #点击按钮_加1帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.press("right")

def Sub1Frame_button_click(): #点击按钮_减1帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.press("left")

def Sub6Frames_button_click(): #点击按钮_减6帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.press("left", presses=6)

def Add6Frames_button_click(): #点击按钮_加6帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.press("right", presses=6)

def PreviousKey_button_click(): #点击按钮_上个帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("alt", "left")

def NextKey_button_click(): #点击按钮_下个帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("alt", "right")

def FrameZero_button_click(): #点击按钮_第0帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("shift", "left")

def FrameEnd_button_click(): #点击按钮_结束帧
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("shift", "right")

selected = False #用于全选/取消点击按钮的判断
def SelectAll_button_click(): #点击按钮_全选/取消
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    global selected
    if not selected:
        pyautogui.hotkey("ctrl", "a")
        selected = True
    else:
        pyautogui.press("esc")
        selected = False

def Timeline_button_click(): #点击按钮_开关时间线
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "[")

def Style_button_click(): #点击按钮_开关样式栏
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "]")

def Actions_button_click(): #点击按钮_开关动作栏
    #获取上次活动窗口
    window_found = active_window()
    if not window_found: #如果没找到,就停止向下执行
        return
    #模拟按下键盘
    pyautogui.hotkey("ctrl", "k")

#创建主窗口
root = tk.Tk()
w_w = 298
w_h = 271
root.geometry(f"{w_w}x{w_h}") #设置窗口大小
root.resizable(False, False) #窗口宽度与高度是否可以改变(固定窗口大小)
root.overrideredirect(True) #禁用默认标题栏
root.attributes('-topmost', 1) #将窗口置于其他窗口之上

#设置窗口背景色
root.configure(bg="#1E1E1E")

#创建顶部区域
top_frame = tk.Frame(root)
top_frame.pack(fill=tk.X)

topl_width = w_w-40 #拖动区域宽度
topr_width = w_w-topl_width #关闭区域宽度

#创建拖动窗口的区域
drag_frame = tk.Frame(top_frame, width=topl_width, height=20, bg="#BFBFBF", cursor="fleur")
drag_frame.pack_propagate(False) #根据内部内容自动调整大小,True将会超出父窗口
drag_frame.pack(side="left")

#创建关闭窗口的区域
close_frame = tk.Frame(top_frame, width=topr_width, height=20, bg="#AB4040")
close_frame.pack_propagate(False)
close_frame.pack(side="right")

#创建底部按钮区域5
bottom_frame5 = tk.Frame(root, bg="#1E1E1E")
bottom_frame5.pack(padx=1, pady=0, fill=tk.X) #设置按钮容器边距

#创建底部按钮5
SelectAll = tk.Button(bottom_frame5, text="Select All\nCancel", width=5, height=2, borderwidth=0, cursor="hand2", command=SelectAll_button_click)
SelectAll.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Timeline = tk.Button(bottom_frame5, text="Timeline", width=5, height=2, borderwidth=0, cursor="hand2", command=Timeline_button_click)
Timeline.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Style = tk.Button(bottom_frame5, text="Style", width=5, height=2, borderwidth=0, cursor="hand2", command=Style_button_click)
Style.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Actions = tk.Button(bottom_frame5, text="Actions", width=5, height=2, borderwidth=0, cursor="hand2", command=Actions_button_click)
Actions.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)

#创建底部按钮区域4
bottom_frame4 = tk.Frame(root, bg="#1E1E1E")
bottom_frame4.pack(padx=1, pady=0, fill=tk.X) #设置按钮容器边距

#创建底部按钮4
Sub1Frame = tk.Button(bottom_frame4, text="-1Frame", width=5, height=2, borderwidth=0, cursor="hand2", command=Sub1Frame_button_click)
Sub1Frame.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Sub6Frames = tk.Button(bottom_frame4, text="-6Frames", width=5, height=2, borderwidth=0, cursor="hand2", command=Sub6Frames_button_click)
Sub6Frames.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
PreviousKey = tk.Button(bottom_frame4, text="Previous\nKey", width=5, height=2, borderwidth=0, cursor="hand2", command=PreviousKey_button_click)
PreviousKey.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
FrameEnd = tk.Button(bottom_frame4, text="Frame\nEnd", width=5, height=2, borderwidth=0, cursor="hand2", command=FrameEnd_button_click)
FrameEnd.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)

#创建底部按钮区域3
bottom_frame3 = tk.Frame(root, bg="#1E1E1E")
bottom_frame3.pack(padx=1, pady=0, fill=tk.X) #设置按钮容器边距

Add1Frame = tk.Button(bottom_frame3, text="+1Frame", width=5, height=2, borderwidth=0, cursor="hand2", command=Add1Frame_button_click)
Add1Frame.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Add6Frames = tk.Button(bottom_frame3, text="+6Frames", width=5, height=2, borderwidth=0, cursor="hand2", command=Add6Frames_button_click)
Add6Frames.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
NextKey = tk.Button(bottom_frame3, text="Next\nKey", width=5, height=2, borderwidth=0, cursor="hand2", command=NextKey_button_click)
NextKey.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
FrameZero = tk.Button(bottom_frame3, text="Frame\nZero", width=5, height=2, borderwidth=0, cursor="hand2", command=FrameZero_button_click)
FrameZero.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)

#创建底部按钮区域2
bottom_frame2 = tk.Frame(root, bg="#1E1E1E")
bottom_frame2.pack(padx=1, pady=0, fill=tk.X) #设置按钮容器边距

#创建底部按钮2
Cut = tk.Button(bottom_frame2, text="Cut", width=5, height=2, borderwidth=0, cursor="hand2", command=Cut_button_click)
Cut.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
FreezeKeys = tk.Button(bottom_frame2, text="Freeze\nKeys", width=5, height=2, borderwidth=0, cursor="hand2", command=FreezeKeys_button_click)
FreezeKeys.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Save = tk.Button(bottom_frame2, text="Save", width=5, height=2, borderwidth=0, cursor="hand2", command=Save_button_click)
Save.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Redo = tk.Button(bottom_frame2, text="Redo", width=5, height=2, borderwidth=0, cursor="hand2", command=Redo_button_click)
Redo.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)

#创建底部按钮区域
bottom_frame = tk.Frame(root, bg="#1E1E1E")
bottom_frame.pack(padx=1, pady=0, fill=tk.X) #设置按钮容器边距

#创建底部按钮
Copy = tk.Button(bottom_frame, text="Copy", width=5, height=2, borderwidth=0, cursor="hand2", command=Copy_button_click)
Copy.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Paste = tk.Button(bottom_frame, text="Paste", width=5, height=2, borderwidth=0, cursor="hand2", command=Paste_button_click)
Paste.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Backspace = tk.Button(bottom_frame, text="Back\nspace", width=5, height=2, borderwidth=0, cursor="hand2", command=Backspace_button_click)
Backspace.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)
Undo = tk.Button(bottom_frame, text="Undo", width=5, height=2, borderwidth=0, cursor="hand2", command=Undo_button_click)
Undo.pack(side="left", padx=1, pady=1, fill=tk.X, expand=True)

#设置所有按钮字体的大小
set_button_font(root)

#绑定鼠标事件以实现左侧窗口拖动
def start_drag(event):
    root.x = event.x
    root.y = event.y

def drag(event):
    deltax = event.x - root.x
    deltay = event.y - root.y
    x = root.winfo_x() + deltax
    y = root.winfo_y() + deltay
    root.geometry(f"{w_w}x{w_h}+{x}+{y}")

drag_frame.bind("<Button-1>", start_drag)
drag_frame.bind("<B1-Motion>", drag)

#右侧窗口关闭函数
def close_window(event):
    #保存窗口位置用于下次恢复
    x = root.winfo_x()
    y = root.winfo_y()
    save_window_position(x, y)
    root.destroy()

close_frame.bind("<Button-1>", close_window)

#获取屏幕的宽度和高度
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()

#临时文件路径
temp_file_path = os.path.join(os.environ.get("TEMP"), "HQC_window_position.pkl")

def save_window_position(x, y):
    #将窗口位置保存到临时文件
    with open(temp_file_path, "wb") as file:
        pickle.dump((x, y), file)

def load_window_position():
    #从临时文件加载保存的窗口位置
    if os.path.exists(temp_file_path):
        with open(temp_file_path, "rb") as file:
            return pickle.load(file)
    else:
        return None

def center_window(root):
    #将窗口显示在屏幕中央
    x = (screen_width - w_w) // 2
    y = (screen_height - w_h) // 2
    root.geometry(f"{w_w}x{w_h}+{x}+{y}")

def apply_saved_window_position(root):
    #应用保存的窗口位置
    position = load_window_position()
    if position:
        x, y = position
        root.geometry(f"+{x}+{y}")
    else:
        center_window(root)

#每次窗口移动或调整大小时保存窗口位置
def on_window_move(event):
    x = root.winfo_x()
    y = root.winfo_y()
    save_window_position(x, y)

root.bind('<Configure>', on_window_move)

#应用保存的窗口位置或显示在屏幕中央
apply_saved_window_position(root)

#运行程序
root.mainloop()
I'm from China, currently using: Moho 15 » Win10 System
:D :D :D :D :D :D :D :D :D :D :D
User avatar
synthsin75
Posts: 10264
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: HQC - Hover Window Quick Click Widget (Win)

Post by synthsin75 »

You didn't have the source code in the download when I checked it. And it doesn't help when you say "If you want to add malicious code, pay me $10 to help you join."
You only have 18 posts on this forum, so you don't have enough history here for people to just trust you.

I would still advise anyone interested in this to compile it for themselves, as there's no way to tell if there's extra code in the exe.
User avatar
570295535
Posts: 32
Joined: Sat Feb 04, 2023 9:32 am

Re: HQC - Hover Window Quick Click Widget (Win)

Post by 570295535 »

synthsin75 wrote: Sat Jun 29, 2024 12:48 pm You didn't have the source code in the download when I checked it. And it doesn't help when you say "If you want to add malicious code, pay me $10 to help you join."
You only have 18 posts on this forum, so you don't have enough history here for people to just trust you.

I would still advise anyone interested in this to compile it for themselves, as there's no way to tell if there's extra code in the exe.
I started learning from scratch, went through 13 iterations of versions, and made hundreds of modifications before finally making it. So easily hand over the source code, I would definitely hesitate.

That "$10" is just my mockery of your unreasonable request for source code from others.

Moreover, the number of posts is not a basis for judging a person's good or bad.

Ah, I lament that the world today is full of malice. Even if you do something good, you must first prove your innocence. Even if you prove your innocence, you still have to be labeled as a villain, It truly chills the heart.
I'm from China, currently using: Moho 15 » Win10 System
:D :D :D :D :D :D :D :D :D :D :D
User avatar
synthsin75
Posts: 10264
Joined: Mon Jan 14, 2008 11:20 pm
Location: Oklahoma
Contact:

Re: HQC - Hover Window Quick Click Widget (Win)

Post by synthsin75 »

Tough. I'm just trying to help out the members of this forum.

I realize you're new here, and might think it's odd for people to warn others of potential risks, but I think that's the helpful thing to do.
The alternative would be to just turn a blind eye to someone potentially spreading malicious software to many people I consider friends.
I have no reason to believe your intentions are malicious, but I also don't know you, or your programming work, well enough to assume you're completely benign.
No one should use software from an unknown source. This is just basic computer security.

I know programming can be hard work, and as a Lua scripter for Moho, everything I share is open source. But when I do, it's to help the community.
Even when I post a compiled exe, I share the source code, so anyone can see it's safe to use (or compile it themselves). Trust is earned, not deserved.
Post Reply