""" \ Base class for Dialogs. Also contains a few useful utility functions """ # dialog.py # Python class for Dialog Boxes in PythonWin. import win32con import win32ui # sob - 2to3 doesn't see this as a relative import :( from pywin.mfc import window def dllFromDll(dllid): "given a 'dll' (maybe a dll, filename, etc), return a DLL object" if dllid == None: return None elif type("") == type(dllid): return win32ui.LoadLibrary(dllid) else: try: dllid.GetFileName() except AttributeError: raise TypeError("DLL parameter must be None, a filename or a dll object") return dllid class Dialog(window.Wnd): "Base class for a dialog" def __init__(self, id, dllid=None): """id is the resource ID, or a template dllid may be None, a dll object, or a string with a dll name""" # must take a reference to the DLL until InitDialog. self.dll = dllFromDll(dllid) if type(id) == type([]): # a template dlg = win32ui.CreateDialogIndirect(id) else: dlg = win32ui.CreateDialog(id, self.dll) window.Wnd.__init__(self, dlg) self.HookCommands() self.bHaveInit = None def HookCommands(self): pass def OnAttachedObjectDeath(self): self.data = self._obj_.data window.Wnd.OnAttachedObjectDeath(self) # provide virtuals. def OnOK(self): self._obj_.OnOK() def OnCancel(self): self._obj_.OnCancel() def OnInitDialog(self): self.bHaveInit = 1 if self._obj_.data: self._obj_.UpdateData(0) return 1 # I did NOT set focus to a child window. def OnDestroy(self, msg): self.dll = None # theoretically not needed if object destructs normally. # DDX support def AddDDX(self, *args): self._obj_.datalist.append(args) # Make a dialog object look like a dictionary for the DDX support def __bool__(self): return True def __len__(self): return len(self.data) def __getitem__(self, key): return self.data[key] def __setitem__(self, key, item): self._obj_.data[key] = item # self.UpdateData(0) def keys(self): return list(self.data.keys()) def items(self): return list(self.data.items()) def values(self): return list(self.data.values()) # XXX - needs py3k work! def has_key(self, key): return key in self.data class PrintDialog(Dialog): "Base class for a print dialog" def __init__( self, pInfo, dlgID, printSetupOnly=0, flags=( win32ui.PD_ALLPAGES | win32ui.PD_USEDEVMODECOPIES | win32ui.PD_NOPAGENUMS | win32ui.PD_HIDEPRINTTOFILE | win32ui.PD_NOSELECTION ), parent=None, dllid=None, ): self.dll = dllFromDll(dllid) if type(dlgID) == type([]): # a template raise TypeError("dlgID parameter must be an integer resource ID") dlg = win32ui.CreatePrintDialog(dlgID, printSetupOnly, flags, parent, self.dll) window.Wnd.__init__(self, dlg) self.HookCommands() self.bHaveInit = None self.pInfo = pInfo # init values (if PrintSetup is called, values still available) flags = pInfo.GetFlags() self["toFile"] = flags & win32ui.PD_PRINTTOFILE != 0 self["direct"] = pInfo.GetDirect() self["preview"] = pInfo.GetPreview() self["continuePrinting"] = pInfo.GetContinuePrinting() self["curPage"] = pInfo.GetCurPage() self["numPreviewPages"] = pInfo.GetNumPreviewPages() self["userData"] = pInfo.GetUserData() self["draw"] = pInfo.GetDraw() self["pageDesc"] = pInfo.GetPageDesc() self["minPage"] = pInfo.GetMinPage() self["maxPage"] = pInfo.GetMaxPage() self["offsetPage"] = pInfo.GetOffsetPage() self["fromPage"] = pInfo.GetFromPage() self["toPage"] = pInfo.GetToPage() # these values updated after OnOK self["copies"] = 0 self["deviceName"] = "" self["driverName"] = "" self["printAll"] = 0 self["printCollate"] = 0 self["printRange"] = 0 self["printSelection"] = 0 def OnInitDialog(self): self.pInfo.CreatePrinterDC() # This also sets the hDC of the pInfo structure. return self._obj_.OnInitDialog() def OnCancel(self): del self.pInfo def OnOK(self): """DoModal has finished. Can now access the users choices""" self._obj_.OnOK() pInfo = self.pInfo # user values flags = pInfo.GetFlags() self["toFile"] = flags & win32ui.PD_PRINTTOFILE != 0 self["direct"] = pInfo.GetDirect() self["preview"] = pInfo.GetPreview() self["continuePrinting"] = pInfo.GetContinuePrinting() self["curPage"] = pInfo.GetCurPage() self["numPreviewPages"] = pInfo.GetNumPreviewPages() self["userData"] = pInfo.GetUserData() self["draw"] = pInfo.GetDraw() self["pageDesc"] = pInfo.GetPageDesc() self["minPage"] = pInfo.GetMinPage() self["maxPage"] = pInfo.GetMaxPage() self["offsetPage"] = pInfo.GetOffsetPage() self["fromPage"] = pInfo.GetFromPage() self["toPage"] = pInfo.GetToPage() self["copies"] = pInfo.GetCopies() self["deviceName"] = pInfo.GetDeviceName() self["driverName"] = pInfo.GetDriverName() self["printAll"] = pInfo.PrintAll() self["printCollate"] = pInfo.PrintCollate() self["printRange"] = pInfo.PrintRange() self["printSelection"] = pInfo.PrintSelection() del self.pInfo class PropertyPage(Dialog): "Base class for a Property Page" def __init__(self, id, dllid=None, caption=0): """id is the resource ID dllid may be None, a dll object, or a string with a dll name""" self.dll = dllFromDll(dllid) if self.dll: oldRes = win32ui.SetResource(self.dll) if type(id) == type([]): dlg = win32ui.CreatePropertyPageIndirect(id) else: dlg = win32ui.CreatePropertyPage(id, caption) if self.dll: win32ui.SetResource(oldRes) # dont call dialog init! window.Wnd.__init__(self, dlg) self.HookCommands() class PropertySheet(window.Wnd): def __init__(self, caption, dll=None, pageList=None): # parent=None, style,etc): "Initialize a property sheet. pageList is a list of ID's" # must take a reference to the DLL until InitDialog. self.dll = dllFromDll(dll) self.sheet = win32ui.CreatePropertySheet(caption) window.Wnd.__init__(self, self.sheet) if not pageList is None: self.AddPage(pageList) def OnInitDialog(self): return self._obj_.OnInitDialog() def DoModal(self): if self.dll: oldRes = win32ui.SetResource(self.dll) rc = self.sheet.DoModal() if self.dll: win32ui.SetResource(oldRes) return rc def AddPage(self, pages): if self.dll: oldRes = win32ui.SetResource(self.dll) try: # try list style access pages[0] isSeq = 1 except (TypeError, KeyError): isSeq = 0 if isSeq: for page in pages: self.DoAddSinglePage(page) else: self.DoAddSinglePage(pages) if self.dll: win32ui.SetResource(oldRes) def DoAddSinglePage(self, page): "Page may be page, or int ID. Assumes DLL setup" if type(page) == type(0): self.sheet.AddPage(win32ui.CreatePropertyPage(page)) else: self.sheet.AddPage(page) # define some app utility functions. def GetSimpleInput(prompt, defValue="", title=None): """displays a dialog, and returns a string, or None if cancelled. args prompt, defValue='', title=main frames title""" # uses a simple dialog to return a string object. if title is None: title = win32ui.GetMainFrame().GetWindowText() # 2to3 insists on converting 'Dialog.__init__' to 'tkinter.dialog...' DlgBaseClass = Dialog class DlgSimpleInput(DlgBaseClass): def __init__(self, prompt, defValue, title): self.title = title DlgBaseClass.__init__(self, win32ui.IDD_SIMPLE_INPUT) self.AddDDX(win32ui.IDC_EDIT1, "result") self.AddDDX(win32ui.IDC_PROMPT1, "prompt") self._obj_.data["result"] = defValue self._obj_.data["prompt"] = prompt def OnInitDialog(self): self.SetWindowText(self.title) return DlgBaseClass.OnInitDialog(self) dlg = DlgSimpleInput(prompt, defValue, title) if dlg.DoModal() != win32con.IDOK: return None return dlg["result"]