from pywin.mfc import dialog import win32ui, win32con, commctrl, win32api class ListDialog (dialog.Dialog): def __init__ (self, title, list): dialog.Dialog.__init__ (self, self._maketemplate(title)) self.HookMessage (self.on_size, win32con.WM_SIZE) self.HookNotify(self.OnListItemChange, commctrl.LVN_ITEMCHANGED) self.HookCommand(self.OnListClick, win32ui.IDC_LIST1) self.items = list def _maketemplate(self, title): style = win32con.WS_DLGFRAME | win32con.WS_SYSMENU | win32con.WS_VISIBLE ls = ( win32con.WS_CHILD | win32con.WS_VISIBLE | commctrl.LVS_ALIGNLEFT | commctrl.LVS_REPORT ) bs = ( win32con.WS_CHILD | win32con.WS_VISIBLE ) return [ [title, (0, 0, 200, 200), style, None, (8, "MS Sans Serif")], ["SysListView32", None, win32ui.IDC_LIST1, (0, 0, 200, 200), ls], [128, "OK", win32con.IDOK, (10, 0, 50, 14), bs | win32con.BS_DEFPUSHBUTTON], [128, "Cancel",win32con.IDCANCEL,(0, 0, 50, 14), bs], ] def FillList(self): size = self.GetWindowRect() width = size[2] - size[0] - (10) itemDetails = (commctrl.LVCFMT_LEFT, width, "Item", 0) self.itemsControl.InsertColumn(0, itemDetails) index = 0 for item in self.items: index = self.itemsControl.InsertItem(index+1, str(item), 0) def OnListClick(self, id, code): if code==commctrl.NM_DBLCLK: self.EndDialog(win32con.IDOK) return 1 def OnListItemChange(self,std, extra): (hwndFrom, idFrom, code), (itemNotify, sub, newState, oldState, change, point, lparam) = std, extra oldSel = (oldState & commctrl.LVIS_SELECTED)!=0 newSel = (newState & commctrl.LVIS_SELECTED)!=0 if oldSel != newSel: try: self.selecteditem = itemNotify self.butOK.EnableWindow(1) except win32ui.error: self.selecteditem = None def OnInitDialog (self): rc = dialog.Dialog.OnInitDialog (self) self.itemsControl = self.GetDlgItem(win32ui.IDC_LIST1) self.butOK = self.GetDlgItem(win32con.IDOK) self.butCancel = self.GetDlgItem(win32con.IDCANCEL) self.FillList() size = self.GetWindowRect() self.LayoutControls(size[2]-size[0], size[3]-size[1]) self.butOK.EnableWindow(0) # wait for first selection return rc def LayoutControls(self, w, h): self.itemsControl.MoveWindow((0,0,w,h-30)) self.butCancel.MoveWindow((10, h-24, 60, h-4)) self.butOK.MoveWindow((w-60, h-24, w-10, h-4)) def on_size (self, params): lparam = params[3] w = win32api.LOWORD(lparam) h = win32api.HIWORD(lparam) self.LayoutControls(w, h) class ListsDialog(ListDialog): def __init__(self, title, list, colHeadings = ['Item']): ListDialog.__init__(self, title, list) self.colHeadings = colHeadings def FillList(self): index = 0 size = self.GetWindowRect() width = size[2] - size[0] - (10) - win32api.GetSystemMetrics(win32con.SM_CXVSCROLL) numCols = len(self.colHeadings) for col in self.colHeadings: itemDetails = (commctrl.LVCFMT_LEFT, width/numCols, col, 0) self.itemsControl.InsertColumn(index, itemDetails) index = index + 1 index = 0 for items in self.items: index = self.itemsControl.InsertItem(index+1, str(items[0]), 0) for itemno in range(1,numCols): item = items[itemno] self.itemsControl.SetItemText(index, itemno, str(item)) def SelectFromList (title, lst): dlg = ListDialog(title, lst) if dlg.DoModal()==win32con.IDOK: return dlg.selecteditem else: return None def SelectFromLists (title, lists, headings): dlg = ListsDialog(title, lists, headings) if dlg.DoModal()==win32con.IDOK: return dlg.selecteditem else: return None def test(): # print SelectFromList('Single list', [1,2,3]) print(SelectFromLists('Multi-List', [ ('1',1, 'a'), ('2',2, 'b'), ('3',3, 'c' )], ['Col 1', 'Col 2'])) if __name__=='__main__': test()