dialogs – Dialog boxes

Provides for simple dialog boxes, doing just enough to return input from the user using edit controls, dropdown lists and checkboxes. Most interaction is via the dialog(), progress_dialog() or info_dialog() functions. This example offers the user a drop-down list of installed Python directories, a text box to enter a size threshold and a checkbox to indicate whether to email the result:

from winsys import dialogs, registry
SIZE_THRESHOLD_MB = "100"
PYTHONREG = registry.registry(r"hklm\software\python\pythoncore")
version, size_threshold_mb, email_result = dialogs.dialog(
    "Find big files in Python",
    ("Version", [k.InstallPath.get_value ("") for k in PYTHONREG.keys()]),
    ("Bigger than (Mb)", SIZE_THRESHOLD_MB),
    ("Email?", False)
)

All dialogs are resizable horizontally but not vertically. All edit boxes (fields with a default which is a string) accept file-drops, eg from Explorer.

The standard dialog (from dialog()) is modal and returns a tuple of values as soon as [Ok] is pressed or an empty list if [Cancel] is pressed. The progress dialog (from progress_dialog()) is also modal, but passes the tuple of values to a callback which yields update strings which are then displayed in the status box on the dialog. When the callback function completes, the dialog returns the tuple of values to the caller. info_dialog() is intended to be used for, eg, displaying a traceback or other bulky text for which a message box might be awkward. It displays multiline text in a readonly edit control which can be scrolled and select-copied.

Functions

dialogs.dialog(title, *fields)[source]

Shortcut function to populate and run a dialog, returning the button pressed and values saved. After the title, the function expects a series of 2-tuples where the first item is the field label and the second is the default value. This default value determines the type of ui element as follows:

  • list - a drop down list in the order given
  • bool - a checkbox
  • string - an edit control

A third item may be present in the tuple where the second item is a string. This is a callback function. If this is present and is not None, a small button will be added to the right of the corresponding edit control which, when pressed, will call the callback which must return a string to be inserted in the edit control, or None if no change is to be made. This is intended to throw up, eg, a file-browse dialog. A useful default is available as get_filename().

Parameters:
  • title – any string to use as the title of the dialog
  • fields – series of 2-tuples consisting of a name and a default value.
Returns:

the values entered by the user in the order of fields

dialogs.progress_dialog(title, progress_callback, *fields)[source]

Populate and run a dialog with a progress callback which yields messages. Fields are the same as for dialog() but the second parameter is a function which takes the value list as parameters and yields strings as updates. The strings will be displayed in a static control on the dialog while the [Ok] button is disabled until the callback completes, at which point the [Ok] button is enabled again and the tuple of values is returned to the caller.

Note

The progress callback runs inside a thread so any necessary thread-specific preparation must happen, eg invoking pythoncom.CoInitialize.

This example takes a directory from the user and finds the total size of each of its subdirectories, showing the name of each one as it is searched. Finally, it uses utils.size_as_mb() to display a human-redable version of each directory size:

from winsys import dialogs, fs, utils

sizes = {}
def sizer(root):
    for d in fs.dir(root).dirs():
        yield d.name
        sizes[d] = sum(f.size for f in d.flat())

dialogs.progress_dialog(
    "Sizer",
    sizer,
    ("Root", "c:/temp", dialogs.get_folder)
)

for d, size in sorted(sizes.items()):
    print d.name, "=>", utils.size_as_mb(size)
Parameters:
  • title – any string to use as the title of the dialog
  • progress_callback – a function accepting values as per fields and yielding progress as strings
  • fields – series of 2-tuples consisting of a name and a default value
Returns:

the values entered by the user in the order of fields

dialogs.info_dialog(title, text, hwnd=<Unset>)[source]

A dialog with no fields which simply displays information in a read-only multiline edit box. The text can be arbitrarily big but the dialog will only adjust vertically up to a certain point. After that the user may scroll with the keyboard. The text can be selected and copied:

import os, sys
from winsys import dialogs
filepath = os.path.join(sys.prefix, "LICENSE.txt")
dialogs.info_dialog("LICENSE.txt", open(filepath).read())
Parameters:
  • title – any string to use as the title of the dialog
  • info – any (possibly multiline) string to display in the body of the dialog
  • parent_hwnd – optional window handle
dialogs.get_filename(hwnd=None, start_folder=None)[source]

Quick interface to the shell’s browse-for-folder dialog, optionally starting in a particular folder and allowing file and share selection.

Warning

At present this interacts badly with TortoiseHg, causing the interpreter to stack dump.

Classes

class dialogs.BaseDialog(title, parent_hwnd=0)[source]

Basic template for a dialog with one or more fields plus [Ok] and [Cancel] buttons. A simple spacing / sizing algorithm is used. Most of the work is done inside _get_dialog_template() which examines the incoming fields and tries to place them according to their various options.

Initialise the dialog with a title and a list of fields of the form [(label, default), ...].

BUTTONS = [(u'Cancel', 2), (u'Ok', 1)]
BUTTON_W = 36
CALLBACK_W = 12
CONTROL_H = 12
FIELD_W = 159
GUTTER_H = 5
GUTTER_W = 5
IDC_CALLBACK_BASE = 3025
IDC_FIELD_BASE = 2025
IDC_LABEL_BASE = 1025
LABEL_W = 36
MAX_H = 480
MAX_W = 640
W = 210
WM_PROGRESS_COMPLETE = 1026
WM_PROGRESS_MESSAGE = 1025
class dialogs.Dialog(title, fields, progress_callback=<Unset>, parent_hwnd=0)[source]

A general-purpose dialog class for collecting arbitrary information in text strings and handing it back to the user. Only Ok & Cancel buttons are allowed, and all the fields are considered to be strings. The list of fields is of the form: [(label, default), ...] and the values are saved in the same order.

Initialise the dialog with a title and a list of fields of the form [(label, default), ...].

OnCallback(hwnd, field_id)[source]

If the user pressed a callback button associated with a text field, find the field and call its callback with the dialog window and the field’s current value. If anything is returned, put that value back into the field.

OnCancel(hwnd)[source]

If the user presses cancel check to see whether we’re running within a progress thread. If so, set the cancel event and wait for the thread to catch up. Either way, close the dialog with a cancelled state.

OnCommand(hwnd, msg, wparam, lparam)[source]

Handle button presses: OK, Cancel and the callback buttons which are optional for text fields

OnInitDialog(hwnd, msg, wparam, lparam)[source]

Attempt to position the dialog box more or less in the middle of its parent (possibly the desktop). Then force a resize of the dialog controls which should take into account the different label lengths and the dialog’s new size.

OnMinMaxInfo(hwnd, msg, wparam, lparam)[source]

Prevent the dialog from resizing vertically by extracting the window’s current size and using the minmaxinfo message to set the maximum & minimum window heights to be its current height.

OnOk(hwnd)[source]

When OK is pressed, if this isn’t a progress dialog then simply gather the results and return. If this is a progress dialog then start a thread to handle progress via the progress iterator.

OnProgressComplete(hwnd, msg, wparam, lparam)[source]

Respond to the a message signalling that all processing is now complete by re-enabling the ok button, disabling cancel, and setting focus to the ok so a return or space will close the dialog.

OnProgressMessage(hwnd, msg, wparam, lparam)[source]

Respond to a progress update from within the progress thread. LParam will be a pointer to a string containing a utf8-encoded string which is to be displayed in the dialog’s progress static.

OnSize(hwnd, msg, wparam, lparam)[source]

If the dialog box is resized, force a corresponding resize of the controls

corners(l, t, r, b)[source]

Designed to be subclassed (eg by InfoDialog). By default simply returns the values unchanged.

run()[source]

The heart of the dialog box functionality. The call to DialogBoxIndirect kicks off the dialog’s message loop, finally returning via the EndDialog call in OnCommand

BUTTONS = [(u'Cancel', 2), (u'Ok', 1)]
BUTTON_W = 36
CALLBACK_W = 12
CONTROL_H = 12
FIELD_W = 159
GUTTER_H = 5
GUTTER_W = 5
IDC_CALLBACK_BASE = 3025
IDC_FIELD_BASE = 2025
IDC_LABEL_BASE = 1025
LABEL_W = 36
MAX_H = 480
MAX_W = 640
W = 210
WM_PROGRESS_COMPLETE = 1026
WM_PROGRESS_MESSAGE = 1025
class dialogs.InfoDialog(title, info, parent_hwnd=<Unset>)[source]
OnCallback(hwnd, field_id)

If the user pressed a callback button associated with a text field, find the field and call its callback with the dialog window and the field’s current value. If anything is returned, put that value back into the field.

OnCancel(hwnd)

If the user presses cancel check to see whether we’re running within a progress thread. If so, set the cancel event and wait for the thread to catch up. Either way, close the dialog with a cancelled state.

OnCommand(hwnd, msg, wparam, lparam)

Handle button presses: OK, Cancel and the callback buttons which are optional for text fields

OnInitDialog(hwnd, msg, wparam, lparam)

Attempt to position the dialog box more or less in the middle of its parent (possibly the desktop). Then force a resize of the dialog controls which should take into account the different label lengths and the dialog’s new size.

OnMinMaxInfo(hwnd, msg, wparam, lparam)

Prevent the dialog from resizing vertically by extracting the window’s current size and using the minmaxinfo message to set the maximum & minimum window heights to be its current height.

OnOk(hwnd)[source]
OnProgressComplete(hwnd, msg, wparam, lparam)

Respond to the a message signalling that all processing is now complete by re-enabling the ok button, disabling cancel, and setting focus to the ok so a return or space will close the dialog.

OnProgressMessage(hwnd, msg, wparam, lparam)

Respond to a progress update from within the progress thread. LParam will be a pointer to a string containing a utf8-encoded string which is to be displayed in the dialog’s progress static.

OnSize(hwnd, msg, wparam, lparam)

If the dialog box is resized, force a corresponding resize of the controls

corners(l, t, r, b)[source]

Called when the dialog is first initialised: estimate how wide the dialog should be according to the longest line of text

run()

The heart of the dialog box functionality. The call to DialogBoxIndirect kicks off the dialog’s message loop, finally returning via the EndDialog call in OnCommand

BUTTONS = [(u'Cancel', 2), (u'Ok', 1)]
BUTTON_W = 36
CALLBACK_W = 12
CONTROL_H = 12
FIELD_W = 159
GUTTER_H = 5
GUTTER_W = 5
IDC_CALLBACK_BASE = 3025
IDC_FIELD_BASE = 2025
IDC_LABEL_BASE = 1025
LABEL_W = 36
MAX_H = 480
MAX_W = 640
W = 210
WM_PROGRESS_COMPLETE = 1026
WM_PROGRESS_MESSAGE = 1025

Constants

dialogs.BIF = <Constants: {'BROWSEINCLUDEURLS': 128, 'RETURNONLYFSDIRS': 1, 'EDITBOX': 16, 'STATUSTEXT': 4, 'USENEWUI': 80, 'UAHINT': 256, 'BROWSEINCLUDEFILES': 16384, 'NEWDIALOGSTYLE': 64, 'NONEWFOLDERBUTTON': 512, 'BROWSEFORPRINTER': 8192, 'NOTRANSLATETARGETS': 1024, 'SHAREABLE': 32768, 'RETURNFSANCESTORS': 8, 'DONTGOBELOWDOMAIN': 2, 'VALIDATE': 32, 'BROWSEFORCOMPUTER': 4096}>

Styles for browsing for a folder

Name Val Win32
RETURNONLYFSDIRS 0x0001 BIF_RETURNONLYFSDIRS
DONTGOBELOWDOMAIN 0x0002 BIF_DONTGOBELOWDOMAIN
STATUSTEXT 0x0004 BIF_STATUSTEXT
RETURNFSANCESTORS 0x0008 BIF_RETURNFSANCESTORS
EDITBOX 0x0010 BIF_EDITBOX
VALIDATE 0x0020 BIF_VALIDATE
NEWDIALOGSTYLE 0x0040 BIF_NEWDIALOGSTYLE
USENEWUI 0x0050 USENEWUI
BROWSEINCLUDEURLS 0x0080 BIF_BROWSEINCLUDEURLS
UAHINT 0x0100 BIF_UAHINT
NONEWFOLDERBUTTON 0x0200 BIF_NONEWFOLDERBUTTON
NOTRANSLATETARGETS 0x0400 BIF_NOTRANSLATETARGETS
BROWSEFORCOMPUTER 0x1000 BIF_BROWSEFORCOMPUTER
BROWSEFORPRINTER 0x2000 BIF_BROWSEFORPRINTER
BROWSEINCLUDEFILES 0x4000 BIF_BROWSEINCLUDEFILES
SHAREABLE 0x8000 BIF_SHAREABLE
dialogs.BFFM = <Constants: {'ENABLEOK': 1125, 'SETSELECTIONW': 1127, 'SETSTATUSTEXTA': 1124, 'SETSELECTION': 1126, 'VALIDATEFAILEDA': 3, 'SETSTATUSTEXT': 1124, 'SETSTATUSTEXTW': 1128, 'SETSELECTIONA': 1126, 'VALIDATEFAILED': 3, 'INITIALIZED': 1, 'SELCHANGED': 2, 'VALIDATEFAILEDW': 4}>

Part of the browse-for-folder shell mechanism

Name Val Win32
INITIALIZED 0x0001 BFFM_INITIALIZED
SELCHANGED 0x0002 BFFM_SELCHANGED
VALIDATEFAILEDA 0x0003 BFFM_VALIDATEFAILEDA
VALIDATEFAILED 0x0003 BFFM_VALIDATEFAILEDA
VALIDATEFAILEDW 0x0004 BFFM_VALIDATEFAILEDW
SETSTATUSTEXTA 0x0464 BFFM_SETSTATUSTEXTA
SETSTATUSTEXT 0x0464 BFFM_SETSTATUSTEXTA
ENABLEOK 0x0465 BFFM_ENABLEOK
SETSELECTION 0x0466 BFFM_SETSELECTIONA
SETSELECTIONA 0x0466 BFFM_SETSELECTIONA
SETSELECTIONW 0x0467 BFFM_SETSELECTIONW
SETSTATUSTEXTW 0x0468 BFFM_SETSTATUSTEXTW

Exceptions

exception dialogs.x_dialogs(errno=None, errctx=None, errmsg=None)[source]

Base for dialog-related exceptions

References

See also

Using the dialogs module
Cookbook examples of using the accounts module

Table Of Contents

Previous topic

accounts – Users, Groups, SIDs &c.

Next topic

event_logs – Event Logs

This Page