Windows SDK 两种消息类型(Message Types)的区别

本文介绍了Windows系统中系统定义消息和应用定义消息的工作原理及使用规范。系统定义消息由系统发送给应用程序,用于控制应用程序的操作并提供输入信息。每种消息都有独特的标识符和符号常量,用于指示消息的目的。此外,文章还详细列举了不同前缀所对应的窗口类别。对于应用定义的消息,文章解释了如何创建私有消息,并规定了消息标识符的分配范围。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

System-Defined Messages

The system sends or posts a system-defined message when it communicates with an application. It uses these messages to control the operations of applications and to provide input and other information for applications to process. An application can also send or post system-defined messages. Applications generally use these messages to control the operation of control windows created by using preregistered window classes.

Each system-defined message has a unique message identifier and a corresponding symbolic constant (defined in the SDK header files) that states the purpose of the message. For example, the WM_PAINT constant requests that a window paint its contents.

Symbolic constants specify the category to which system-defined messages belong. The prefix of the constant identifies the type of window that can interpret and process the message. Following are the prefixes and their related message categories.

PrefixMessage category
ABMApplication desktop toolbar
BMButton control
CBCombo box control
CBEMExtended combo box control
CDMCommon dialog box
DBTDevice
DLDrag list box
DMDefault push button control
DTMDate and time picker control
EMEdit control
HDMHeader control
HKMHot key control
IPMIP address control
LBList box control
LVMList view control
MCMMonth calendar control
PBMProgress bar
PGMPager control
PSMProperty sheet
RBRebar control
SBStatus bar window
SBMScroll bar control
STMStatic control
TBToolbar
TBMTrackbar
TCMTab control
TTMTooltip control
TVMTree-view control
UDMUp-down control
WMGeneral window

 

General window messages cover a wide range of information and requests, including messages for mouse and keyboard input, menu and dialog box input, window creation and management, and dynamic data exchange (DDE).

 

 


 

 

Application-Defined Messages

An application can create messages to be used by its own windows or to communicate with windows in other processes. If an application creates its own messages, the window procedure that receives them must interpret the messages and provide appropriate processing.

Message-identifier values are used as follows:

  • The system reserves message-identifier values in the range 0x0000 through 0x03FF (the value of WM_USER – 1) for system-defined messages. Applications cannot use these values for private messages.
  • Values in the range 0x0400 (the value of WM_USER) through 0x7FFF are available for message identifiers for private window classes.
  • If your application is marked version 4.0, you can use message-identifier values in the range 0x8000 (WM_APP) through 0xBFFF for private messages.
  • The system returns a message identifier in the range 0xC000 through 0xFFFF when an application calls the RegisterWindowMessage function to register a message. The message identifier returned by this function is guaranteed to be unique throughout the system. Use of this function prevents conflicts that can arise if other applications use the same message identifier for different purposes.
import json import os import threading import PySimpleGUI as sg import telnetlib import time import queue import logging from datetime import datetime # ============== 全局配置 ============== DATA_FILE = 'pyremote_config.json' PROJECTS_FILE = 'projects_config.json' END_STR = "ROUTER_MPU /home\x1b[m # " LOG_FORMAT = '%(asctime)s - %(levelname)s - %(message)s' ENCODING = 'utf-8' BUFFER_SIZE = 4096 CHUNK_SIZE = 10 # 每10个字符发送一次 CHUNK_DELAY = 0.15 # 每个分块之间的延迟(秒) COMMAND_DELAY = 0.5 # 命令之间的延迟(秒) # ============== 日志配置 ============== def setup_logger(): """配置日志系统""" logger = logging.getLogger('RemoteControl') logger.setLevel(logging.DEBUG) # 文件处理器 file_handler = logging.FileHandler('remote_control.log') file_handler.setFormatter(logging.Formatter(LOG_FORMAT)) # 控制台处理器 console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter(LOG_FORMAT)) logger.addHandler(file_handler) logger.addHandler(console_handler) return logger logger = setup_logger() # ============== 项目管理类 ============== class ProjectManager: def __init__(self): self.projects = self.load_projects() def load_projects(self): """加载项目配置""" if os.path.exists(PROJECTS_FILE): try: with open(PROJECTS_FILE, 'r') as f: return json.load(f) except Exception as e: logger.error(f"加载项目配置失败: {e}") return {"projects": []} return {"projects": []} def save_projects(self): """保存项目配置""" try: with open(PROJECTS_FILE, 'w') as f: json.dump(self.projects, f, indent=4) return True except Exception as e: logger.error(f"保存项目配置失败: {e}") return False def add_project(self, name, commands): """添加新项目""" project = { "name": name, "commands": commands, "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } self.projects["projects"].append(project) if self.save_projects(): return project return None def update_project(self, index, name, commands): """更新项目""" if 0 <= index < len(self.projects["projects"]): self.projects["projects"][index]["name"] = name self.projects["projects"][index]["commands"] = commands if self.save_projects(): return True return False def delete_project(self, index): """删除项目""" if 0 <= index < len(self.projects["projects"]): del self.projects["projects"][index] return self.save_projects() return False def import_projects(self, file_path): """导入项目配置""" try: with open(file_path, 'r') as f: imported = json.load(f) # 验证导入格式 if "projects" in imported and isinstance(imported["projects"], list): self.projects = imported return self.save_projects() except Exception as e: logger.error(f"导入项目失败: {e}") return False def export_projects(self, file_path): """导出项目配置""" try: with open(file_path, 'w') as f: json.dump(self.projects, f, indent=4) return True except Exception as e: logger.error(f"导出项目失败: {e}") return False def get_project_commands(self, index): """获取项目的命令列表""" if 0 <= index < len(self.projects["projects"]): return self.projects["projects"][index]["commands"] return [] # ============== 指令执行类(增强版) ============== class CommandExecutor: def __init__(self): self.tn = None self.is_connected = False self.response = "" self.prev_cmd = "" self.log_queue = queue.Queue() self.lock = threading.Lock() self.stop_event = threading.Event() self.pause_event = threading.Event() # 暂停事件 self.last_response = "" self.expected_prompt = END_STR self.current_command_index = -1 # 当前执行命令索引 self.current_command = "" # 当前执行的命令 self.total_commands = 0 # 总命令数 def connect(self, host, port): """连接设备""" try: with self.lock: self.tn = telnetlib.Telnet(host, port, timeout=10) self.is_connected = True self.log_queue.put(f"已连接到 {host}:{port}") # 初始读取以清除欢迎信息 self.read_until_prompt(timeout=3) return True except Exception as e: self.log_queue.put(f"连接失败: {str(e)}") return False def disconnect(self): """断开连接""" with self.lock: if self.tn: try: self.tn.close() except: pass self.is_connected = False self.log_queue.put("连接已断开") def send(self, content): """发送命令(分块发送)""" if not self.is_connected: self.log_queue.put("错误:未连接到设备") return False try: with self.lock: # 保存当前命令 self.current_command = content # 使用正确的编码发送 encoded_content = content.encode(ENCODING) # 分块发送(每10个字符) chunks = [encoded_content[i:i+CHUNK_SIZE] for i in range(0, len(encoded_content), CHUNK_SIZE)] for chunk in chunks: # 检查停止信号 if self.stop_event.is_set(): self.log_queue.put("发送已中止") return False # 检查暂停信号 while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False # 发送分块 self.tn.write(chunk) self.log_queue.put(f"发送分块: {chunk.decode(ENCODING, errors='replace')}") # 添加分块之间的延迟 time.sleep(CHUNK_DELAY) # 发送回车符(模拟敲回车) self.tn.write(b"\r\n") self.log_queue.put("发送回车符") self.log_queue.put(f"完整发送: {content.strip()}") self.prev_cmd = content return True except Exception as e: self.log_queue.put(f"发送命令失败: {str(e)}") return False def read_until_prompt(self, timeout=5): """读取直到遇到提示符""" if not self.is_connected: return "" try: # 使用正确的编码读取 response = self.tn.read_until(self.expected_prompt.encode(ENCODING), timeout=timeout) decoded_response = response.decode(ENCODING, errors='replace') # 移除命令回显 if self.prev_cmd and decoded_response.startswith(self.prev_cmd.strip()): decoded_response = decoded_response[len(self.prev_cmd.strip()):].lstrip() # 移除尾部的提示符 if decoded_response.endswith(self.expected_prompt): decoded_response = decoded_response[:-len(self.expected_prompt)].rstrip() self.last_response = decoded_response self.log_queue.put(decoded_response) return decoded_response except Exception as e: self.log_queue.put(f"接收响应失败: {str(e)}") return "" def execute_commands(self, commands): """执行命令序列(增强版)""" if not self.is_connected: self.log_queue.put("错误:未连接到设备") return False self.stop_event.clear() self.pause_event.clear() self.total_commands = len(commands) self.log_queue.put(f"开始执行 {self.total_commands} 条命令") try: for idx, cmd in enumerate(commands): if self.stop_event.is_set(): self.log_queue.put("命令执行已中止") return False # 设置当前命令索引 self.current_command_index = idx # 检查暂停状态 while self.pause_event.is_set(): time.sleep(0.1) if self.stop_event.is_set(): return False if cmd.strip(): # 跳过空行 # 发送命令 if not self.send(cmd): return False # 等待命令完成 self.read_until_prompt(timeout=10) # 命令间延迟 delay_remaining = COMMAND_DELAY while delay_remaining > 0: if self.stop_event.is_set(): return False if self.pause_event.is_set(): time.sleep(0.1) continue time.sleep(0.1) delay_remaining -= 0.1 self.log_queue.put("命令执行完成") self.current_command_index = -1 return True except Exception as e: self.log_queue.put(f"命令执行失败: {str(e)}") return False def stop_execution(self): """停止当前执行""" self.stop_event.set() self.log_queue.put("正在停止执行...") def pause_execution(self): """暂停当前执行""" if not self.pause_event.is_set(): self.pause_event.set() self.log_queue.put("执行已暂停") return True return False def resume_execution(self): """继续执行""" if self.pause_event.is_set(): self.pause_event.clear() self.log_queue.put("执行已继续") return True return False def get_execution_status(self): """获取执行状态""" return { "is_running": not self.stop_event.is_set() and not self.pause_event.is_set(), "is_paused": self.pause_event.is_set(), "is_stopped": self.stop_event.is_set(), "current_command": self.current_command.strip(), "current_index": self.current_command_index, "total_commands": self.total_commands } # ============== GUI 界面类(增强版) ============== class RemoteControlApp: def __init__(self): self.project_manager = ProjectManager() self.executor = CommandExecutor() self.default_data = self.load_default_data() self.window = None self.setup_gui() self.log_thread = None self.status_update_thread = None self.running = True def load_default_data(self): """加载默认配置""" default_data = { "IP": "71.19.0.120", "port": "1001", "FTP_IP": "71.19.0.120", "芯片名称": "Hi1260SV100", '发送信息': "", "board_local_ip": "71.19.0.53", 'interval': "1", "start_addr": "", "end_addr": "", "文件FTP路径": "", } if os.path.exists(DATA_FILE): try: with open(DATA_FILE, 'r') as f: data = json.load(f) default_data.update({k: data[k] for k in default_data if k in data}) except Exception as e: logger.error(f"加载默认配置失败: {e}") with open(DATA_FILE, 'w') as f: json.dump(default_data, f) else: with open(DATA_FILE, 'w') as f: json.dump(default_data, f) return default_data def save_config(self): """保存配置""" try: values = self.window.read()[1] if self.window else {} with open(DATA_FILE, 'w') as f: json.dump({ "IP": values.get("IP", self.default_data["IP"]), "port": values.get("port", self.default_data["port"]), "FTP_IP": values.get("FTP_IP", self.default_data["FTP_IP"]), "芯片名称": values.get("芯片名称", self.default_data["芯片名称"]), '发送信息': values.get("发送信息", self.default_data["发送信息"]), "board_local_ip": values.get("board_local_ip", self.default_data["board_local_ip"]), 'interval': values.get("interval", self.default_data["interval"]), "start_addr": values.get("start_addr", self.default_data["start_addr"]), "end_addr": values.get("end_addr", self.default_data["end_addr"]), "文件FTP路径": values.get("文件FTP路径", self.default_data["文件FTP路径"]), }, f) return True except Exception as e: logger.error(f"保存配置失败: {e}") return False def create_project_buttons(self): """创建项目按钮区域""" layout = [] projects = self.project_manager.projects["projects"] if not projects: layout.append([sg.Text("没有项目,请添加新项目", text_color='red')]) for i, project in enumerate(projects): row = [ sg.Button(project["name"], key=f'-PROJECT-{i}-', size=(15,1), tooltip=f"创建于: {project['created_at']}\n命令数: {len(project['commands'])}"), sg.Button("一键升级", key=f'-UPGRADE-{i}-', button_color=('white', 'green')), sg.Button("编辑", key=f'-EDIT-{i}-', button_color=('white', 'blue')), sg.Button("删除", key=f'-DELETE-{i}-', button_color=('white', 'red')) ] layout.append(row) # 添加项目管理按钮 layout.append([ sg.Button("添加新项目", key='-ADD-PROJECT-', button_color=('white', 'purple')), sg.Button("导入项目", key='-IMPORT-PROJECTS-'), sg.Button("导出项目", key='-EXPORT-PROJECTS-'), sg.Button("生成模板", key='-CREATE-TEMPLATE-') ]) return layout def edit_project_window(self, index=None): """项目编辑窗口""" project = None if index is not None and 0 <= index < len(self.project_manager.projects["projects"]): project = self.project_manager.projects["projects"][index] layout = [ [sg.Text("项目名称:"), sg.Input(key='-PROJECT-NAME-', default_text=project["name"] if project else "")], [sg.Text("升级指令:")], [sg.Multiline(key='-PROJECT-COMMANDS-', size=(60, 10), default_text='\n'.join(project["commands"]) if project else "", tooltip="每行一个命令,命令将按顺序执行")], [sg.Button("保存", key='-SAVE-PROJECT-'), sg.Button("取消", key='-CANCEL-PROJECT-')] ] window = sg.Window("项目编辑", layout, modal=True) while True: event, values = window.read() if event in (sg.WINDOW_CLOSED, '-CANCEL-PROJECT-'): break elif event == '-SAVE-PROJECT-': name = values['-PROJECT-NAME-'].strip() commands = [cmd.strip() for cmd in values['-PROJECT-COMMANDS-'].split('\n') if cmd.strip()] if not name: sg.popup("项目名称不能为空") continue if index is None: new_project = self.project_manager.add_project(name, commands) if new_project: sg.popup(f"项目 '{name}' 添加成功") break else: if self.project_manager.update_project(index, name, commands): sg.popup(f"项目 '{name}' 更新成功") break sg.popup("操作失败,请查看日志") window.close() return True def setup_gui(self): """设置GUI界面(增强版)""" # 创建主布局 sg.theme('LightBlue1') # 输出区域 output = sg.Multiline( size=(80, 20), key='-OUTPUT-', autoscroll=True, background_color='#f0f0f0', text_color='black' ) # 状态信息区域 status_info = [ sg.Text("当前命令: ", size=(10,1)), sg.Text("无", key='-CURRENT-COMMAND-', size=(40,1), text_color='blue'), sg.Text("进度: ", size=(5,1)), sg.Text("0/0", key='-COMMAND-PROGRESS-', size=(10,1)) ] # 项目列表区域 projects_frame = sg.Frame("项目列表", [ [sg.Column( self.create_project_buttons(), scrollable=True, vertical_scroll_only=True, size=(700, 300), key='-PROJECTS-COLUMN-' )] ], key='-PROJECTS-FRAME-') # 执行控制区域 control_buttons = [ sg.Button('暂停执行', key='-PAUSE-EXECUTION-', button_color=('white', 'orange'), size=(10,1)), sg.Button('继续执行', key='-RESUME-EXECUTION-', button_color=('white', 'green'), size=(10,1)), sg.Button('停止执行', key='-STOP-EXECUTION-', button_color=('white', 'red'), size=(10,1)) ] # 连接状态区域 status_bar = [ sg.Text('●', key='-STATUS-LIGHT-', text_color='red', font=('Arial', 12)), sg.Text("未连接", key='-CONNECTION-STATUS-'), sg.StatusBar("就绪", key='-STATUS-', size=(50, 1)) ] # 主布局 layout = [ [sg.Text('IP:', size=(6,1)), sg.Input(key="IP", default_text=self.default_data["IP"], size=(15,1)), sg.Text('Port:', size=(5,1)), sg.Input(key="port", default_text=self.default_data["port"], size=(8,1)), sg.Button('连接', button_color=('white', 'green')), sg.Button('断开连接', button_color=('white', 'red'))], [projects_frame], status_info, # 执行控制按钮 [sg.Frame("执行控制", [control_buttons], key='-CONTROL-FRAME-')], [sg.Text("发送信息:", size=(8,1)), sg.Input(key='发送信息', size=(50, 1), default_text=self.default_data["发送信息"])], [sg.Button('ROUTER_MPU下发送'), sg.Button('Shell下发送'), sg.Text('每隔', size=(3,1)), sg.Input(key='interval', default_text=self.default_data["interval"], size=(5,1)), sg.Text("秒", size=(2,1)), sg.Button('定时发送'), sg.Button("停止定时发送")], [sg.Button('接收1s')], [sg.Text('芯片名称:', size=(8,1)), sg.Input(key="芯片名称", default_text=self.default_data["芯片名称"], size=(15,1)), sg.Text('文件FTP路径:', size=(10,1)), sg.Input(key="文件FTP路径", default_text=self.default_data["文件FTP路径"], size=(30,1))], [sg.Text('FTP_IP:', size=(6,1)), sg.Input(key="FTP_IP", default_text=self.default_data["FTP_IP"], size=(15,1)), sg.Text('单板IP:', size=(6,1)), sg.Input(key="board_local_ip", default_text=self.default_data["board_local_ip"], size=(15,1))], [sg.Text("SLT测试用"), sg.Button('重新获取sdk.out'), sg.Button("一键升级MT1"), sg.Button("一键升级MT2")], [sg.Button("使用说明", button_color=('white', 'blue'))], [sg.Text('起始地址:', size=(8,1)), sg.Input(key='start_addr', default_text=self.default_data["start_addr"], size=(12,1)), sg.Text('结束地址:', size=(8,1)), sg.Input(key='end_addr', default_text=self.default_data["end_addr"], size=(12,1)), sg.Button('dump寄存器')], [output], status_bar ] self.window = sg.Window('远程单板连接工具', layout, finalize=True, resizable=True) self.update_status_light() self.start_log_thread() self.start_status_update_thread() def update_status_light(self): """更新状态指示灯""" color = 'green' if self.executor.is_connected else 'red' status = "已连接" if self.executor.is_connected else "未连接" self.window['-STATUS-LIGHT-'].update(text_color=color) self.window['-CONNECTION-STATUS-'].update(status) def update_output(self): """更新输出区域""" while not self.executor.log_queue.empty(): try: message = self.executor.log_queue.get_nowait() current_text = self.window['-OUTPUT-'].get() self.window['-OUTPUT-'].update(current_text + message + '\n') except queue.Empty: break def start_log_thread(self): """启动日志更新线程""" self.log_thread = threading.Thread(target=self.log_update_loop, daemon=True) self.log_thread.start() def log_update_loop(self): """日志更新循环""" while self.running: self.update_output() time.sleep(0.1) def start_status_update_thread(self): """启动状态更新线程""" self.status_update_thread = threading.Thread(target=self.status_update_loop, daemon=True) self.status_update_thread.start() def status_update_loop(self): """状态更新循环""" while self.running: # 更新执行状态 status = self.executor.get_execution_status() # 更新当前命令显示 if status["current_command"]: self.window['-CURRENT-COMMAND-'].update(status["current_command"]) # 更新进度显示 if status["current_index"] >= 0 and status["total_commands"] > 0: progress_text = f"{status['current_index'] + 1}/{status['total_commands']}" self.window['-COMMAND-PROGRESS-'].update(progress_text) # 更新按钮状态 if status["is_running"]: self.window['-PAUSE-EXECUTION-'].update(disabled=False) self.window['-RESUME-EXECUTION-'].update(disabled=True) self.window['-STOP-EXECUTION-'].update(disabled=False) elif status["is_paused"]: self.window['-PAUSE-EXECUTION-'].update(disabled=True) self.window['-RESUME-EXECUTION-'].update(disabled=False) self.window['-STOP-EXECUTION-'].update(disabled=False) else: self.window['-PAUSE-EXECUTION-'].update(disabled=True) self.window['-RESUME-EXECUTION-'].update(disabled=True) self.window['-STOP-EXECUTION-'].update(disabled=True) time.sleep(0.2) def refresh_project_list(self): """刷新项目列表""" self.window['-PROJECTS-COLUMN-'].update(visible=False) self.window['-PROJECTS-COLUMN-'].update(self.create_project_buttons()) self.window['-PROJECTS-COLUMN-'].update(visible=True) def run(self): """运行主循环(增强版)""" stop_loop = 0 interval = 10000 loop_msg = "" while True: event, values = self.window.read(timeout=100) if event == sg.WINDOW_CLOSED: break # 更新输出区域 self.update_output() # 连接管理 if event == '连接': if values["IP"] and values["port"]: if self.executor.connect(values["IP"], int(values["port"])): self.window['-STATUS-'].update("已连接") self.update_status_light() else: sg.popup("请输入IP和端口") elif event == '断开连接': self.executor.disconnect() self.window['-STATUS-'].update("已断开") self.update_status_light() # 项目管理 elif event == '-ADD-PROJECT-': self.edit_project_window() self.refresh_project_list() elif event.startswith('-EDIT-'): index = int(event.split('-')[2]) self.edit_project_window(index) self.refresh_project_list() elif event.startswith('-DELETE-'): index = int(event.split('-')[2]) if self.project_manager.delete_project(index): sg.popup("项目删除成功") self.refresh_project_list() else: sg.popup("项目删除失败") elif event == '-IMPORT-PROJECTS-': file_path = sg.popup_get_file("选择项目配置文件", file_types=(("JSON Files", "*.json"),)) if file_path and self.project_manager.import_projects(file_path): sg.popup("项目导入成功") self.refresh_project_list() else: sg.popup("项目导入失败") elif event == '-EXPORT-PROJECTS-': file_path = sg.popup_get_file("保存项目配置文件", save_as=True, file_types=(("JSON Files", "*.json"),)) if file_path and self.project_manager.export_projects(file_path): sg.popup("项目导出成功") else: sg.popup("项目导出失败") elif event == '-CREATE-TEMPLATE-': self.create_template_file() sg.popup("模板文件已生成: projects_template.json") # 一键升级 elif event.startswith('-UPGRADE-'): index = int(event.split('-')[2]) if index < len(self.project_manager.projects["projects"]): project = self.project_manager.projects["projects"][index] self.window['-STATUS-'].update(f"执行 {project['name']} 升级...") # 在新线程中执行升级 threading.Thread( target=self.execute_project_upgrade, args=(index,), daemon=True ).start() # 执行控制 elif event == '-PAUSE-EXECUTION-': if self.executor.pause_execution(): self.window['-STATUS-'].update("执行已暂停") elif event == '-RESUME-EXECUTION-': if self.executor.resume_execution(): self.window['-STATUS-'].update("执行已继续") elif event == '-STOP-EXECUTION-': self.executor.stop_execution() self.window['-STATUS-'].update("执行已停止") # 其他原有功能... elif event == 'ROUTER_MPU下发送': if self.save_config() and values["发送信息"]: self.executor.send(values["发送信息"]) # 等待响应 self.executor.read_until_prompt() elif event == 'Shell下发送': if self.save_config() and values["发送信息"]: self.executor.send(values["发送信息"]) # 等待响应 self.executor.read_until_prompt() elif event == '定时发送': if self.save_config() and values["发送信息"] and values["interval"]: try: interval = float(values["interval"]) if interval <= 0: raise ValueError("间隔必须大于0") loop_msg = values["发送信息"] threading.Thread( target=self.periodic_send, args=(loop_msg, interval), daemon=True ).start() except Exception as e: sg.popup(f"无效的间隔: {str(e)}") else: sg.popup("请输入发送信息和有效间隔") elif event == "停止定时发送": self.executor.stop_execution() # 其他事件处理 elif event == '接收1s': self.executor.read_until_prompt(timeout=1) elif event == 'dump寄存器': if values["start_addr"] and values["end_addr"]: self.executor.send(f"dump {values['start_addr']} {values['end_addr']}") self.executor.read_until_prompt() elif event == '重新获取sdk.out': self.executor.send("get_sdk.out") self.executor.read_until_prompt() elif event == '一键升级MT1': self.executor.send("upgrade_mt1") self.executor.read_until_prompt() elif event == '一键升级MT2': self.executor.send("upgrade_mt2") self.executor.read_until_prompt() elif event == '使用说明': self.show_help() self.running = False self.executor.disconnect() if self.log_thread: self.log_thread.join(timeout=1.0) if self.status_update_thread: self.status_update_thread.join(timeout=1.0) self.window.close() def execute_project_upgrade(self, index): """执行项目升级(增强版)""" commands = self.project_manager.get_project_commands(index) if commands: # 重置进度显示 self.window['-CURRENT-COMMAND-'].update("") self.window['-COMMAND-PROGRESS-'].update("0/0") success = self.executor.execute_commands(commands) self.window['-STATUS-'].update("升级完成" if success else "升级失败") else: self.executor.log_queue.put("错误:项目没有配置命令") def periodic_send(self, message, interval): """周期性发送消息(优化版)""" while not self.executor.stop_event.is_set(): self.executor.send(message) # 等待响应 self.executor.read_until_prompt() # 等待指定间隔 time.sleep(interval) def show_help(self): """显示使用说明(增强版)""" help_text = """ === 远程单板连接工具使用说明 === 1. 连接管理: - 输入IP和端口后点击"连接"按钮 - 状态指示灯显示连接状态(红:未连接, 绿:已连接) 2. 项目管理: - 添加项目:点击"添加新项目"按钮 - 编辑项目:点击项目右侧的"编辑"按钮 - 删除项目:点击项目右侧的"删除"按钮 - 一键升级:点击项目右侧的"一键升级"按钮 - 导入/导出:支持JSON格式配置导入导出 3. 命令执行控制: - 暂停执行:点击"暂停执行"按钮 - 继续执行:点击"继续执行"按钮 - 停止执行:点击"停止执行"按钮 - 进度显示:显示当前执行的命令和进度 4. 发送机制: - 分块发送:每条命令按10字符分块发送 - 回车发送:每条命令发送后自动发送回车符 - 命令间延迟:每条命令之间有0.5秒延迟 - 命令同步:每条命令发送后等待响应完成 5. 特殊功能: - dump寄存器:输入起始和结束地址 - SLT测试:提供快速测试按钮 6. 优化说明: - 使用UTF-8编码避免乱码 - 命令发送后自动等待响应完成 - 自动过滤命令回显和提示符 - 实时显示执行状态和进度 """ sg.popup(help_text, title="使用说明", font=("Arial", 11)) def create_template_file(self): """创建项目配置模板""" try: template = { "projects": [ { "name": "项目A", "commands": [ "ifconfig eth0 192.168.0.100", "ftpget -u user -p pass 192.168.0.1 /home/firmware.bin firmware.bin", "flash -w 0 0x0000000 0xa000000 0x2000000" ], "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") }, { "name": "项目B", "commands": [ "ifconfig eth0 192.168.0.101", "ping 192.168.0.1", "reboot" ], "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } ] } with open("projects_template.json", 'w') as f: json.dump(template, f, indent=4) return True except Exception as e: logger.error(f"创建模板文件失败: {e}") return False # ============== 主程序入口 ============== if __name__ == "__main__": # 启动应用 try: app = RemoteControlApp() app.run() except Exception as e: logger.exception("应用程序崩溃") sg.popup_error(f"应用程序发生致命错误: {str(e)}")
最新发布
07-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值