我有以下 Python MFC 代码。我有一个列表框,其中填充了一些值,当用户单击这些值时,我希望静态文本控件使用当前选择进行更新。这段代码有两个问题。第一个是文本控件中的值仅在我第一次单击列表框时更新。第二个是该值滞后于列表框中实际选定的值,可能是因为控件在调用我的处理程序代码后处理单击。如果您能帮助解决这两个问题,我将不胜感激。
一件奇怪的事情(也许是一个线索)是,当我将鼠标放在“确定”按钮上,但将鼠标移开以向上移动时,静态文本确实会按照我的预期进行更新。
我已经在控件和对话框上尝试过 RedrawWindow()、UpdateWindow()、ShowWindow(),但似乎没有任何区别。
import win32con
from pywin.mfc import dialog
IDC_LIST = 9000
IDC_TEXT = 9001
class ChooserDialog(dialog.Dialog):
def __init__(self):
DIALOGTEMPLATE = [
["Test", (0, 0, 254, 199), win32con.WS_CAPTION | win32con.DS_MODALFRAME, None, (8, "MS SansSerif")],
[128, "OK", win32con.IDOK, (197,178,50,14), win32con.BS_PUSHBUTTON | win32con.WS_VISIBLE],
["listbox", "List", IDC_LIST, (7,7,177,186), win32con.WS_VISIBLE],
["static", "", IDC_TEXT, (197,7,50,160), win32con.WS_CHILD | win32con.WS_VISIBLE]
]
dialog.Dialog.__init__(self, DIALOGTEMPLATE)
def OnInitDialog(self):
rc = dialog.Dialog.OnInitDialog(self)
for i in ["one", "two", "three"]:
self.GetDlgItem(IDC_LIST).AddString(i)
self.HookCommand(self.OnNotify, IDC_LIST)
return rc
def OnNotify(self, ctrl, action):
if ctrl == IDC_LIST:
selected = self.GetDlgItem(IDC_LIST).GetCurSel()
self.SetDlgItemText(IDC_TEXT, "%d" % selected)
self.GetDlgItem(IDC_TEXT).RedrawWindow()
return 1
dia = ChooserDialog()
dia.DoModal()
最佳答案
代码的第一个问题是没有为列表框控件设置 win32con.LBS_NOTIFY 样式。如果未设置,您将不会收到来自 LB 的任何消息。我收到的几条消息是由于对话框中的其他事件引起的。
第二个问题是我使用了 HookCommand(),它拦截命令并允许您处理它们。相反,我希望 HookMessage() 仅获取通知。看来在控件更新后会调用通知,所以这正是我想要的。
根据MSDN文档,LBN_SELCHANGE通知是通过WM_COMMAND消息接收的。看来我必须订阅对话框中的所有 WM_COMMAND 消息,然后在我的处理程序中过滤它们。 LBN_SELCHANGE 文档解释了传递的内容,结合 HookMessage() Python 文档,您可以了解如何处理它。
这是工作代码:
import win32con
from pywin.mfc import dialog
IDC_LIST = 9500
IDC_TEXT = 9501
class ChooserDialog(dialog.Dialog):
def __init__(self):
DIALOGTEMPLATE = [
["Test", (0, 0, 254, 199), win32con.WS_CAPTION | win32con.DS_MODALFRAME, None, (8, "MS SansSerif")],
[128, "OK", win32con.IDOK, (197,178,50,14), win32con.BS_PUSHBUTTON | win32con.WS_VISIBLE],
["listbox", "List", IDC_LIST, (7,7,177,186), win32con.WS_VISIBLE|win32con.LBS_NOTIFY],
["static", "", IDC_TEXT, (197,7,50,160), win32con.WS_CHILD | win32con.WS_VISIBLE]
]
dialog.Dialog.__init__(self, DIALOGTEMPLATE)
def OnInitDialog(self):
rc = dialog.Dialog.OnInitDialog(self)
for i in ["one", "two", "three"]:
self.GetDlgItem(IDC_LIST).AddString(i)
self.HookMessage(self.OnNotifyCommand, win32con.WM_COMMAND)
return rc
def OnNotifyCommand(self, data):
msg_id = data[1] # should always be WM_COMMAND
wParam = data[2]
lParam = data[3]
list_id = wParam & 0xffff
notification_code = (wParam & 0xffff0000) >> 16
if list_id != IDC_LIST: return # not our list box.
if notification_code != win32con.LBN_SELCHANGE: return # Not a change of selection
selected = self.GetDlgItem(IDC_LIST).GetCurSel()
self.SetDlgItemText(IDC_TEXT, "%d"%selected)
dia = ChooserDialog()
dia.DoModal()
关于Python MFC : Updating static text in response to events,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30650763/