Python MFC:更新静态文本以响应事件
Python MFC: Updating static text in response to events
我有以下 Python MFC 代码。我有一个列表框,其中填充了一些值,当用户单击这些值时,我希望静态文本控件使用当前选择进行更新。这段代码有两个问题。首先是文本控件中的值仅在我第一次单击列表框时更新。第二个是该值落后于列表框中的实际选定值,大概是因为控件在我的处理程序代码被调用后处理了点击。如果能帮助我解决这些问题,我将不胜感激。
一件奇怪的事情(也许是一个线索)是,当我将鼠标放在 'OK' 按钮上但移开鼠标向上时,静态文本确实会按照我的预期进行更新。
我已经在控件和对话框上尝试了 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 代码。我有一个列表框,其中填充了一些值,当用户单击这些值时,我希望静态文本控件使用当前选择进行更新。这段代码有两个问题。首先是文本控件中的值仅在我第一次单击列表框时更新。第二个是该值落后于列表框中的实际选定值,大概是因为控件在我的处理程序代码被调用后处理了点击。如果能帮助我解决这些问题,我将不胜感激。
一件奇怪的事情(也许是一个线索)是,当我将鼠标放在 'OK' 按钮上但移开鼠标向上时,静态文本确实会按照我的预期进行更新。
我已经在控件和对话框上尝试了 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()