Windows 快速启动器

在日常工作和学习中,我们经常需要快速访问某些功能或资源,例如打开常用网站、启动应用程序或执行特定命令。Linux 用户可以通过 alias 快速实现这些操作,但在 Windows 上缺乏类似的原生支持。本文将介绍如何使用 Python 开发一个 隐藏式文本输入框程序,模拟 Linux 的 alias 功能,实现快速启动和访问。


功能概述

该程序的核心功能如下:

  1. 隐藏式界面:默认情况下,程序界面隐藏,按下热键后显示。

  2. 快速输入:通过键盘输入关键字,按下回车键后执行相应操作。

  3. 自定义映射:通过配置文件(如 store.txt)定义关键字与操作的映射关系。

  4. 快速打开网站:输入关键字后,自动打开对应的 URL。

  5. 打开文件夹:输入关键字后,打开指定的文件夹。

  6. 启动应用程序:输入关键字后,启动指定的应用程序。

  7. 执行系统命令:输入关键字后,执行系统命令(如打开服务管理器)。

  8. 单实例运行:确保程序只运行一个实例,避免重复启动。


实现原理

1. 隐藏式界面

使用 tkinter 创建一个无标题栏的文本输入框界面,默认隐藏。通过全局热键(如 Alt + Win + Z)显示界面,并将焦点设置到输入框。

2. 关键字映射

通过读取配置文件(如 store.txt),将关键字与操作(如 URL、文件夹路径、应用程序路径或系统命令)关联起来。例如:

 
google https://www.google.com u
python https://www.python.org u
ubunt D:\ubunt f
services %SystemRoot%\system32\services.msc o
notepad C:\Windows\System32\notepad.exe o

 


3. 快速执行

输入关键字后,按下回车键,程序会根据配置文件执行相应操作(如打开浏览器访问 URL、打开文件夹、启动应用程序或执行系统命令)。

4. 单实例运行

使用 psutil 检查程序是否已经运行,避免重复启动。


代码实现

以下是完整的 Python 代码:

python
复制
import tkinter as tk
import keyboard
import ctypes
import sys
import os
import psutil
import webbrowser
import subprocess
import time

class StoreItem:
    def __init__(self, keyword, content, type_):
        self.keyword = keyword
        self.content = content
        self.type_ = type_

class Store:
    def __init__(self, file_path):
        self.file_path = file_path
        self.items = {}
        self.last_modified = 0
        self.load()

    def load(self):
        if not os.path.exists(self.file_path):
            print(f"错误:未找到文件 {self.file_path},请确保 store.txt 和脚本在同一目录下。")
            return

        self.last_modified = os.path.getmtime(self.file_path)
        self.items.clear()

        with open(self.file_path, "r", encoding="utf-8") as file:
            for line in file:
                columns = line.strip().split()
                if len(columns) == 3:
                    keyword, content, type_ = columns
                    self.items[keyword] = StoreItem(keyword, content, type_)

    def get_item(self, keyword):
        if os.path.getmtime(self.file_path) > self.last_modified:
            self.load()
        return self.items.get(keyword)

def is_already_running():
    current_pid = os.getpid()
    for proc in psutil.process_iter(['pid', 'name']):
        try:
            if proc.info['name'] == os.path.basename(sys.argv[0]) and proc.info['pid'] != current_pid:
                return True
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass
    return False

if is_already_running():
    print("程序已经在运行中,退出当前实例。")
    sys.exit(0)

user32 = ctypes.windll.user32
imm32 = ctypes.windll.imm32

def show_window():
    if not root.winfo_viewable():
        root.deiconify()
    root.lift()
    root.focus_force()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    window_width = root.winfo_reqwidth()
    window_height = root.winfo_reqheight()
    x = screen_width - window_width - 20
    y = 20
    root.geometry(f"+{x}+{y}")
    text_entry.focus_set()
    text_entry.delete(0, tk.END)
    switch_to_english()

def hide_window():
    root.withdraw()

def on_enter(event):
    input_text = text_entry.get()
    if input_text.strip():
        ontext(input_text)
    text_entry.delete(0, tk.END)
    hide_window()

def handle_action(item):
    if item.type_ == "u":
        webbrowser.open(item.content)
        print(f"已打开 URL: {item.content}")
    elif item.type_ == "f":
        os.startfile(item.content)
        print(f"已打开文件夹: {item.content}")
    elif item.type_ == "o":
        subprocess.run(item.content, shell=True)
        print(f"已执行命令: {item.content}")

def ontext(key):
    item = store.get_item(key)
    if item:
        handle_action(item)
    else:
        print(f"未找到关键字为 {key} 的记录。")

def switch_to_english():
    hwnd = user32.GetForegroundWindow()
    himc = imm32.ImmGetContext(hwnd)
    if himc:
        imm32.ImmSetOpenStatus(himc, False)
        imm32.ImmReleaseContext(hwnd, himc)

root = tk.Tk()
root.overrideredirect(True)
root.configure(bg="white")

text_entry = tk.Entry(
    root,
    width=20,
    font=("Arial", 12),
    bd=0,
    highlightthickness=1,
    justify="left"
)
text_entry.pack(padx=10, pady=10)

root.withdraw()

text_entry.bind("<Return>", on_enter)
keyboard.add_hotkey("alt+windows+z", show_window)
keyboard.add_hotkey("esc", hide_window)
text_entry.bind("<FocusIn>", lambda event: switch_to_english())

script_dir = os.path.dirname(os.path.abspath(__file__))
store_path = os.path.join(script_dir, "store.txt")
store = Store(store_path)

root.mainloop()

 


配置文件示例

在 store.txt 文件中添加以下内容:

 
google https://www.google.com u
python https://www.python.org u
ubunt D:\ubunt f
services %SystemRoot%\system32\services.msc o
notepad C:\Windows\System32\notepad.exe o

 

 


功能说明

  1. 打开 URL

    • 输入 google,打开 https://www.google.com

    • 输入 python,打开 https://www.python.org

  2. 打开文件夹

    • 输入 ubunt,打开 D:\ubunt 文件夹。

  3. 启动应用程序或执行系统命令

    • 输入 services,打开服务管理器。

    • 输入 notepad,启动记事本。


使用方法

  1. 将 Python 脚本和 store.txt 文件放在同一目录下。

  2. 运行 Python 脚本。

  3. 按下 Alt + Win + Z 显示界面,输入关键字后按 Enter 键。

  4. 程序会根据配置文件执行相应操作。


打包为可执行文件

使用 PyInstaller 将脚本打包为 Windows 可执行文件:

bash
复制
pyinstaller --onefile --windowed main.py

生成的 main.exe 文件位于 dist 文件夹中。

 


总结

通过抽象 StoreItem 和 Store 类,代码逻辑更加清晰和模块化。快速启动器 不仅支持打开网址,还能打开文件夹、启动应用程序和执行系统命令。你可以根据需要在 store.txt 中添加更多映射关系,实现快速访问常用资源的目标。希望这个工具能帮助你提高工作效率!

 

新修改的代码:

import tkinter as tk
import keyboard  # 用于监听全局热键
import ctypes  # 用于切换输入法
import psutil  # 用于检查进程
import sys,webbrowser, os, subprocess


# 检查是否已经有相同进程在运行
def is_already_running():
    current_pid = os.getpid()
    for proc in psutil.process_iter(['pid', 'name']):
        try:
            # 检查进程名称和当前脚本名称是否相同
            if proc.info['name'] == os.path.basename(sys.argv[0]) and proc.info['pid'] != current_pid:
                print(os.path.basename(sys.argv[0]))
                os.system("pause")
                return True
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            pass
    return False

# 如果已经有相同进程在运行,退出程序
if is_already_running():
    print("程序已经在运行中,退出当前实例。")
    sys.exit(0)

# 获取输入法相关的 Windows API
user32 = ctypes.windll.user32
imm32 = ctypes.windll.imm32
def show_window():
    # 确保窗口完全销毁后重建的问题 (针对某些Tk版本兼容性)
    if not root.winfo_exists():
        return
    
    # 强制窗口显示并更新界面
    root.deiconify()
    root.update_idletasks()  # 关键!强制完成所有UI渲染
    
    # 计算精确的窗口尺寸(使用实际渲染后的尺寸)
    window_width = root.winfo_width()
    window_height = root.winfo_height()
    
    # 获取屏幕有效工作区(排除任务栏)
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    
    # 计算右侧定位坐标(考虑多显示器情况)
    x = screen_width - window_width - 20
    y = 20
    
    # 应用定位(先移动窗口再置顶)
    root.geometry(f"+{x}+{y}")
    
    # 窗口层级和焦点控制
    root.lift()  # 置顶窗口
    root.attributes("-topmost", True)  # 强制置顶属性
    root.after(100, lambda: root.attributes("-topmost", False))  # 100ms后取消置顶
    
    # 焦点控制(多重保障)
    text_entry.focus_set()
    root.after(10, text_entry.focus_force)  # 延迟强制焦点
    
    # 清空输入框
    text_entry.delete(0, tk.END)
    
    # 输入法控制(延迟执行确保焦点生效)
    root.after(50, switch_to_english)

# 输入法切换函数增强版
def switch_to_english():
    try:
        # 获取当前焦点窗口
        hwnd = user32.GetForegroundWindow()
        
        # 获取线程输入法上下文d
        thread_id = user32.GetWindowThreadProcessId(hwnd, None)
        himc = imm32.ImmGetContext(hwnd)
        
        if himc:
            # 强制关闭输入法
            imm32.ImmSetOpenStatus(himc, False)
            imm32.ImmReleaseContext(hwnd, himc)
            
            # 额外发送ESC键确保清除输入状态
            keyboard.send('esc', do_press=True, do_release=True)
    except Exception as e:
        print(f"输入法切换失败: {str(e)}")

# 定义隐藏窗口的函数
def hide_window():
    root.withdraw()  # 隐藏窗口
    
# 定义处理 Enter 键的函数
def on_enter(event):
    input_text = text_entry.get()  # 获取输入框内容
    if input_text.strip():  # 如果输入内容不为空
        ontext(input_text)  # 调用 ontext 函数并传递输入文本
    text_entry.delete(0, tk.END)  # 清空输入框内容
    hide_window()  # 隐藏窗口
def onUrl(keyword, content):
    url = content  # 获取 URL
    webbrowser.open(url)  # 通过浏览器打开 URL
    #os.startfile(url)cxycc
    print(f"已打开 URL: {url}")
import subprocess
def onObj(keyword, content):
    try:
        #subprocess.run(content, check=True)
        #webbrowser.open(content)
        #os.system(f'start "{content}"')
        process = subprocess.Popen(content)
        print(f'start "{content}"')
        print(f"成功打开并等待 {content} 完成")
    except subprocess.CalledProcessError as e:
        print(f"程序返回非零退出码: {e}")
    except FileNotFoundError:
        print(f"文件未找到: {content}")
    except Exception as e:
        print(f"打开文件时出错: {e}")
    
def onKey(keyword, content, type_):
    if type_ == "u":
        onUrl(keyword, content)
    elif type_ == "o":
        onObj(keyword, content)

# 定义 ontext 函数
def ontext(key):
    print(f"输入的文本是:{key}")  # 这里可以替换为你的自定义逻辑
    # 获取脚本所在目录的绝对路径
    script_dir = os.path.dirname(os.path.abspath(__file__))
    # 拼接 store.txt 的绝对路径
    store_path = os.path.join(script_dir, "store.csv")

    # 检查文件是否存在
    if not os.path.exists(store_path):
        print(f"错误:未找到文件 {store_path},请确保 store.txt 和脚本在同一目录下。")
        return
    # 打开 store.txt 文件
    with open(store_path, mode='r', encoding='utf-8') as file:
        for line in file:
            # 按空格分割每行数据
            columns = line.strip().split(",")
            if len(columns) == 3:  # 确保每行有3列
                keyword, content, type_ = columns
                print(f"{keyword}/{content}/{type_}")
                if keyword != key:
                    continue
                onKey(keyword, content, type_)
                return
    print(f"未找到关键字为 {key} 的记录。")


# 定义切换为英文输入法的函数
def switch_to_english():
    # 获取当前激活窗口的句柄
    hwnd = user32.GetForegroundWindow()
    # 获取当前线程的输入法上下文
    himc = imm32.ImmGetContext(hwnd)
    if himc:
        # 设置输入法为英文
        imm32.ImmSetOpenStatus(himc, False)  # 关闭输入法
        imm32.ImmReleaseContext(hwnd, himc)

# 创建主窗口
root = tk.Tk()

# 移除标题栏和边框
root.overrideredirect(True)

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

# 创建一个文本输入框
text_entry = tk.Entry(
    root,
    width=20,  # 文本框长度为60
    font=("Arial", 12),
    bd=0,
    highlightthickness=1,
    justify="left"  # 文本框靠左输入
)
text_entry.pack(padx=10, pady=10)

# 默认隐藏窗口
root.withdraw()

# 绑定 Enter 键事件
text_entry.bind("<Return>", on_enter)
try:
    # 绑定 Alt+Win+Z 热键
    keyboard.add_hotkey("alt+win+z", show_window, suppress=True)
except Exception as e:
    print(f"出现错误: {e}")

# 绑定 Esc 键隐藏窗口
keyboard.add_hotkey("esc", hide_window)

# 绑定输入框获取焦点事件
text_entry.bind("<FocusIn>", lambda event: switch_to_english())

# 运行主循环
root.mainloop()

 

 
 
posted @ 2025-01-21 14:51  荣--  阅读(695)  评论(4)    收藏  举报