Dialog Base的 UpdateCommandUI Handler

本文详细介绍了MFC框架下如何使用UpdateCommandUIHandler更新界面元素的状态,包括菜单和工具栏项的使能、禁用及选中状态更新等。通过具体的代码示例,展示了如何在对话框中实现这一功能。

http://www.debuglab.com/knowledge/dlgupdateui.html

Dialog Base俊 UpdateCommandUI Handler甫 崔磊.


1.夸距

MFC俊辑 Frame 扁馆狼 扩档绰 Menu, Toolbar殿捞 UpdateCammandUI Handler俊 悼累俊 蝶扼 Enable/Disable, Check惑怕啊 啊瓷茄单, Dialog 扁馆狼 扩档绰 捞繁 悼累捞 冈龙 臼嚼聪促. 恐衬搁 CFrameWnd俊绰 捞繁 扁瓷甸捞 备泅登绢 乐瘤父 CDialog俊绰 绝扁 锭巩涝聪促. 荤角 捞繁 扁瓷阑 持扁绰 奖瘤绰 臼嚼聪促. 历档 CFrameWnd狼 家胶甫 蝶扼啊焊搁辑 败快 舅酒陈嚼聪促. 捞 规过阑 荤侩窍搁 Dialog俊 乐绰 牧飘费鳖瘤 CmdUpdateUI Handler甫 悼累 矫懦 荐 乐嚼聪促.


2.夯巩

琴缴篮 WM_KICKIDLE捞扼绰 皋技瘤甫 贸府窍绰单 乐嚼聪促. 捞 皋技瘤绰 MSDN俊 UNDOCUMENT荤亲捞骨肺 茫酒毫档 绝阑 疤聪促. 捞抚栏肺焊搁 Idle惑怕俊 惯积登绰 皋技瘤涝聪促. 捞 何盒俊辑 Menu客 ToolBar 弊府绊 Control甸狼 惑怕甫 力绢窍搁邓聪促. Modal Dialog俊辑父 犬牢秦好瘤父 Modeless俊辑绰 酒流 犬牢 给秦好嚼聪促. 梅何茄 CDialogEx 努贰胶甫 惑加罐酒 荤侩窍搁 邓聪促.


3.抗力

////////////// 

// DialogEx.H



// Implementation

protected:

virtual void OnUpdateCmdUI_Menu(CCmdTarget* pTarget,

BOOL bDisableIfNoHndler); // 眠啊

virtual void OnUpdateCmdUI_ToolBar(CCmdTarget* pTarget,

BOOL bDisableIfNoHndler); // 眠啊



// Generated message map functions

//{{AFX_MSG(CDialogEx)

//}}AFX_MSG

afx_msg LRESULT OnKickIdle(WPARAM , LPARAM ); // 眠啊

DECLARE_MESSAGE_MAP()



///////////////

// DialogEx.CPP

BEGIN_MESSAGE_MAP(CDialogEx, CDialog)

//{{AFX_MSG_MAP(CDialogEx)

//}}AFX_MSG_MAP

ON_MESSAGE(WM_KICKIDLE, OnKickIdle)

END_MESSAGE_MAP()



class CToolCmdUI : public CCmdUI // class private to this file !

{

public: // re-implementations only

virtual void Enable(BOOL bOn);

virtual void SetCheck(int nCheck);

virtual void SetText(LPCTSTR lpszText);

};



void CToolCmdUI::Enable(BOOL bOn)

{

m_bEnableChanged = TRUE;

CToolBar* pToolBar = (CToolBar*)m_pOther;

ASSERT(pToolBar != NULL);

ASSERT_KINDOF(CToolBar, pToolBar);

ASSERT(m_nIndex < m_nIndexMax);



UINT nNewStyle = pToolBar->GetButtonStyle(m_nIndex) & ~TBBS_DISABLED;

if (!bOn)

{

nNewStyle |= TBBS_DISABLED;

// WINBUG: If a button is currently pressed and then is disabled

// COMCTL32.DLL does not unpress the button, even after the mouse

// button goes up! We work around this bug by forcing TBBS_PRESSED

// off when a button is disabled.

nNewStyle &= ~TBBS_PRESSED;

}

ASSERT(!(nNewStyle & TBBS_SEPARATOR));

pToolBar->SetButtonStyle(m_nIndex, nNewStyle);

}



void CToolCmdUI::SetCheck(int nCheck)

{

ASSERT(nCheck >= 0 && nCheck <= 2); // 0=>off, 1=>on, 2=>indeterminate

CToolBar* pToolBar = (CToolBar*)m_pOther;

ASSERT(pToolBar != NULL);

ASSERT_KINDOF(CToolBar, pToolBar);

ASSERT(m_nIndex < m_nIndexMax);



UINT nNewStyle = pToolBar->GetButtonStyle(m_nIndex) &

~(TBBS_CHECKED | TBBS_INDETERMINATE);

if (nCheck == 1)

nNewStyle |= TBBS_CHECKED;

else if (nCheck == 2)

nNewStyle |= TBBS_INDETERMINATE;

ASSERT(!(nNewStyle & TBBS_SEPARATOR));

pToolBar->SetButtonStyle(m_nIndex, nNewStyle | TBBS_CHECKBOX);

}



void CToolCmdUI::SetText(LPCTSTR)

{

// ignore it

}



LRESULT CDialogEx::OnKickIdle(WPARAM wParam, LPARAM lParam)

{

OnUpdateCmdUI_Menu(this, TRUE);

OnUpdateCmdUI_ToolBar(this, TRUE);

UpdateDialogControls(this, FALSE);



return 0;

}



void CDialogEx::OnUpdateCmdUI_Menu(CCmdTarget* pTarget,

BOOL bDisableIfNoHndler)

{

CMenu* pMenu = GetMenu();

if (!pMenu)

return;



CCmdUI state;

for (UINT nIndex = 0; nIndex < pMenu->GetMenuItemCount(); nIndex++)

{

CMenu* pSubMenu = pMenu->GetSubMenu(nIndex);

state.m_nIndexMax = pSubMenu->GetMenuItemCount();

for (UINT i = 0; i < state.m_nIndexMax; i++)

{

state.m_nIndex = i;

state.m_nID = pSubMenu->GetMenuItemID(i);

state.m_pMenu = pSubMenu;

state.DoUpdate(pTarget, bDisableIfNoHndler);

}

}

}



void CDialogEx::OnUpdateCmdUI_ToolBar(CCmdTarget* pTarget,

BOOL bDisableIfNoHndler)

{

CToolBar *pToolBar = (CToolBar*)GetDlgItem(AFX_IDW_TOOLBAR);

if (!pToolBar)

return;



CToolCmdUI state;

state.m_pOther = pToolBar;

state.m_nIndexMax = pToolBar->GetToolBarCtrl().GetButtonCount();



for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++)

{

// get buttons state

TBBUTTON button;

pToolBar->GetToolBarCtrl().GetButton(state.m_nIndex, &button);

state.m_nID = button.idCommand;



// ignore separators

if (!(button.fsStyle & TBSTYLE_SEP))

{

// allow reflections

if (pToolBar->OnCmdMsg(0,

MAKELONG((int)CN_UPDATE_COMMAND_UI,

WM_COMMAND+WM_REFLECT_BASE), &state, NULL))

continue;



// allow the toolbar itself to have update handlers

if (pToolBar->OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))

continue;



// allow the owner to process the update

state.DoUpdate(this, TRUE);

}

}

}

4.曼绊

Coduguru, MFC 家胶  
修改::未解析的引用 'Callable',,类 'EventType' 的未解析的特性引用 'START_COMMAND',,类 'EventType' 的未解析的特性引用 'DIALOG_OPEN',,代码# core/base_module.py import logging import json import time import uuid from typing import Any, Dict, Optional from dataclasses import dataclass, field # 需要导入事件相关类 try: from core.event_center import Event, EventType, event_center from core.app_context import app_context except ImportError: # 备用导入方案 from .event_center import Event, EventType, event_center from .app_context import app_context class BaseModule: """所有模块的基类(增强版)""" MODULE_ID = "" # 子类必须覆盖 def __init__(self, module_name: str): if not self.MODULE_ID: raise NotImplementedError("子类必须定义MODULE_ID") self.module_name = module_name self.logger = logging.getLogger(module_name) self._handlers = {} self.dynamic_data = {} self._dialog_opened = False # 初始化事件订阅 self._setup_subscriptions() self._initialize() def _setup_subscriptions(self): """设置事件订阅""" def filtered_handler(event: Event): if event.target == self.MODULE_ID: self._handle_start_command(event) event_center.subscribe(EventType.START_COMMAND.value, filtered_handler) event_center.subscribe(EventType.MODULE_RUN.value, self._handle_module_run) def _initialize(self): """初始化模块""" ready_event = Event( event_id=str(int(time.time())), type=EventType.MODULE_READY.value, source=str(self.MODULE_ID), target='pool' ) event_center.publish(ready_event) def _handle_start_command(self, event: Event): """处理开始命令事件""" self.logger.debug(f"收到开始命令事件:{event.type} from {event.source}") if not self._dialog_opened: self.logger.info(f"正在打开模块 {self.MODULE_ID} 的界面") self._open_dialog() self._dialog_opened = True else:
08-20
检查代码,分析模块3的前端和后端不能够建立连接的原因::::# core/base_module.py import logging import json import time import uuid from typing import Any, Dict, Optional, Callable, Union # 添加Union导入 from dataclasses import dataclass, field from enum import Enum from abc import ABC, abstractmethod # 添加抽象基类支持 # 定义核心事件类型枚举 class EventType(str, Enum): """系统事件类型枚举""" START_COMMAND = "start_command" DIALOG_OPEN = "dialog_open" MODULE_RUN = "module_run" MODULE_READY = "module_ready" MODULE_COMPLETE = "module_complete" DATA_SUBMIT = "data_submit" UI_UPDATE = "ui_update" ERROR = "error" # 事件数据类 @dataclass class Event: """事件数据类""" type: Union[EventType, str] # 使用Union类型 source: str target: Optional[str] = None data: Optional[Dict[str, Any]] = field(default_factory=dict) token: Optional[str] = None event_id: str = field(default_factory=lambda: str(uuid.uuid4())) timestamp: float = field(default_factory=time.time) # 事件中心实现 class EventCenter: def __init__(self): self._subscribers = {} def subscribe(self, event_type: Union[EventType, str], handler: Callable): """订阅事件""" type_str = event_type.value if isinstance(event_type, EventType) else event_type if type_str not in self._subscribers: self._subscribers[type_str] = [] self._subscribers[type_str].append(handler) def publish(self, event: Event): """发布事件""" handlers = self._subscribers.get( event.type.value if isinstance(event.type, EventType) else event.type, [] ) for handler in handlers: try: handler(event) except Exception as e: logging.error(f"事件处理失败: {e}") # 应用上下文 class AppContext: """应用上下文占位类""" pass # 全局实例 event_center = EventCenter() app_context = AppContext() class BaseModule: _modules = {} # 存储所有已注册模块 @classmethod def register_module(cls, module_id, module_instance): """注册模块到中央管理器""" cls._modules[module_id] = module_instance @classmethod def get_module(cls, module_id): """获取模块实例""" return cls._modules.get(module_id) @classmethod def get_all_modules(cls): """获取所有注册模块""" return list(cls._modules.values()) class BaseModule(ABC): # 改为抽象基类 """所有模块的基类(增强版)""" MODULE_ID = "base_module" # 默认值,子类必须覆盖 def __init__(self, module_name: str): if not self.MODULE_ID or self.MODULE_ID == "base_module": raise NotImplementedError("子类必须定义MODULE_ID") self.module_name = module_name self.logger = logging.getLogger(module_name) self._handlers = {} self.dynamic_data = {} self._dialog_opened = False self._active = True # 初始化事件订阅 self._setup_subscriptions() self._initialize() def _setup_subscriptions(self): """设置事件订阅""" # 订阅START_COMMAND事件 event_center.subscribe(EventType.START_COMMAND, self._handle_start_command) # 订阅MODULE_RUN事件 event_center.subscribe(EventType.MODULE_RUN, self._handle_module_run) self.logger.info(f"模块 {self.MODULE_ID} 事件订阅完成") def _initialize(self): """初始化模块并发送就绪事件""" ready_event = Event( type=EventType.MODULE_READY, source=self.MODULE_ID, data={"module": self.module_name} ) event_center.publish(ready_event) self.logger.info(f"模块 {self.MODULE_ID} 初始化完成") def _handle_start_command(self, event: Event): """处理开始命令事件""" if not self._active: self.logger.warning(f"模块 {self.MODULE_ID} 未激活,忽略命令") return self.logger.debug(f"收到开始命令事件:{event.type} from {event.source}") if not self._dialog_opened: self.logger.info(f"正在打开模块 {self.MODULE_ID} 的界面") self._open_dialog() self._dialog_opened = True else: self.logger.warning(f"模块 {self.MODULE_ID} 的对话框已打开,忽略重复命令") def _handle_module_run(self, event: Event): """处理模块运行事件""" if event.target == self.MODULE_ID and self._active: self.logger.info(f"收到模块运行指令: {event.data}") self.run_module(event.data) @abstractmethod def _open_dialog(self): """打开模块对话框(子类必须实现)""" pass @abstractmethod def run_module(self, parameters: Dict[str, Any]): """运行模块主逻辑(子类必须实现)""" pass def send_completion_event(self, result: Dict[str, Any]): """发送模块完成事件""" complete_event = Event( type=EventType.MODULE_COMPLETE, source=self.MODULE_ID, data={"result": result} ) event_center.publish(complete_event) self.logger.info(f"模块 {self.MODULE_ID} 完成处理") def activate(self): """激活模块""" self._active = True self.logger.info(f"模块 {self.MODULE_ID} 已激活") def deactivate(self): """停用模块""" self._active = False self.logger.info(f"模块 {self.MODULE_ID} 已停用") def cleanup(self): """模块清理资源""" self._dialog_opened = False self.logger.info(f"模块 {self.MODULE_ID} 已清理资源")
08-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值