【问题标题】:Python MFC: Updating static text in response to eventsPython MFC:更新静态文本以响应事件
【发布时间】:2015-06-05 22:10:56
【问题描述】:

我有以下 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()

【问题讨论】:

  • RedrawWindow 应该已经完成​​了,您可以将其添加到您的示例代码中吗?
  • @Mark: 应该在对话框还是控件上?
  • 在控件本身上。静态控件,因为它们是“静态的”并且不会改变,所以不会自动重绘自己,而是必须被告知。
  • 好的。那很有意思。我的第一个版本使用第二个列表框而不是静态文本,并且有同样的问题。

标签: python mfc


【解决方案1】:

代码的第一个问题是没有为列表框控件设置 win32con.LBS_NOTIFY 样式。如果未设置,您将不会收到来自 LB 的任何消息。我收到的几条消息是由于对话框中的其他事件引起的。

第二个问题是我使用了 HookCommand(),它拦截命令并允许你处理它们。相反,我希望 HookMes​​sage() 只获取通知。似乎在控件更新后会调用通知,所以这正是我想要的。

根据 MSDN 文档,LBN_SELCHANGE 通知是通过 WM_COMMAND 消息接收的。看来我必须订阅对话框中的所有 WM_COMMAND 消息,然后在我的处理程序中过滤它们。 LBN_SELCHANGE 文档解释了传递的内容,结合 HookMes​​sage() 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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-18
    • 2016-03-02
    • 2018-03-24
    • 2012-02-03
    • 2020-10-11
    • 1970-01-01
    • 2020-12-11
    • 2013-07-20
    相关资源
    最近更新 更多