Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions src/pymsgbox/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,12 @@
buttonsFrame = None


def _alertTkinter(text="", title="", button=OK_TEXT, root=None, timeout=None):
def _alertTkinter(text="", title="", button=OK_TEXT, root=None, timeout=None, icon=None):
"""Displays a simple message box with text and a single OK button. Returns the text of the button clicked on."""
assert TKINTER_IMPORT_SUCCEEDED, "Tkinter is required for pymsgbox"
text = str(text)
retVal = _buttonbox(
msg=text, title=title, choices=[str(button)], root=root, timeout=timeout
msg=text, title=title, choices=[str(button)], root=root, timeout=timeout, icon=icon
)
if retVal is None:
return button
Expand All @@ -122,7 +122,7 @@ def _alertTkinter(text="", title="", button=OK_TEXT, root=None, timeout=None):


def _confirmTkinter(
text="", title="", buttons=(OK_TEXT, CANCEL_TEXT), root=None, timeout=None
text="", title="", buttons=(OK_TEXT, CANCEL_TEXT), root=None, timeout=None, icon=None
):
"""Displays a message box with OK and Cancel buttons. Number and text of buttons can be customized. Returns the text of the button clicked on."""
assert TKINTER_IMPORT_SUCCEEDED, "Tkinter is required for pymsgbox"
Expand All @@ -133,29 +133,30 @@ def _confirmTkinter(
choices=[str(b) for b in buttons],
root=root,
timeout=timeout,
icon=icon
)


confirm = _confirmTkinter


def _promptTkinter(text="", title="", default="", root=None, timeout=None):
def _promptTkinter(text="", title="", default="", root=None, timeout=None, icon=None):
"""Displays a message box with text input, and OK & Cancel buttons. Returns the text entered, or None if Cancel was clicked."""
assert TKINTER_IMPORT_SUCCEEDED, "Tkinter is required for pymsgbox"
text = str(text)
return __fillablebox(
text, title, default=default, mask=None, root=root, timeout=timeout
text, title, default=default, mask=None, root=root, timeout=timeout, icon=icon
)


prompt = _promptTkinter


def _passwordTkinter(text="", title="", default="", mask="*", root=None, timeout=None):
def _passwordTkinter(text="", title="", default="", mask="*", root=None, timeout=None, icon=None):
"""Displays a message box with text input, and OK & Cancel buttons. Typed characters appear as *. Returns the text entered, or None if Cancel was clicked."""
assert TKINTER_IMPORT_SUCCEEDED, "Tkinter is required for pymsgbox"
text = str(text)
return __fillablebox(text, title, default, mask=mask, root=root, timeout=timeout)
return __fillablebox(text, title, default, mask=mask, root=root, timeout=timeout, icon=icon)


password = _passwordTkinter
Expand All @@ -181,7 +182,22 @@ def timeoutBoxRoot():
__enterboxText = TIMEOUT_RETURN_VALUE


def _buttonbox(msg, title, choices, root=None, timeout=None):
def _seticon(window: tk.Tk, icon: str):
try:
img = tk.PhotoImage(file=icon)
window.iconphoto(True, img)
return
except tk.TclError:
pass

try:
window.iconbitmap(icon)
return
except tk.TclError:
pass


def _buttonbox(msg, title, choices, root=None, timeout=None, icon=None):
"""
Display a msg, a title, and a set of buttons.
The buttons are defined by the members of the choices list.
Expand All @@ -190,6 +206,7 @@ def _buttonbox(msg, title, choices, root=None, timeout=None):
@arg msg: the msg to be displayed.
@arg title: the window title
@arg choices: a list or tuple of the choices to be displayed
@arg icon: the window icon (tk bitmap name, png, gif, ico or xbm file)
"""
global boxRoot, __replyButtonText, __widgetTexts, buttonsFrame

Expand All @@ -205,6 +222,9 @@ def _buttonbox(msg, title, choices, root=None, timeout=None):
boxRoot = tk.Tk()
boxRoot.withdraw()

if icon:
_seticon(boxRoot, icon)

boxRoot.title(title)
boxRoot.iconname("Dialog")
boxRoot.geometry(rootWindowPosition)
Expand Down Expand Up @@ -311,7 +331,7 @@ def __cancelButtonEvent(event):
boxRoot.quit()


def __fillablebox(msg, title="", default="", mask=None, root=None, timeout=None):
def __fillablebox(msg, title="", default="", mask=None, root=None, timeout=None, icon=None):
"""
Show a box in which a user can enter some text.
You may optionally specify some default text, which will appear in the
Expand All @@ -337,6 +357,9 @@ def __fillablebox(msg, title="", default="", mask=None, root=None, timeout=None)
boxRoot = tk.Tk()
boxRoot.withdraw()

if icon:
_seticon(boxRoot, icon)

boxRoot.title(title)
boxRoot.iconname("Dialog")
boxRoot.geometry(rootWindowPosition)
Expand Down
21 changes: 17 additions & 4 deletions src/pymsgbox/_native_win.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,22 +50,34 @@
messageBoxFunc = ctypes.windll.user32.MessageBoxW


def _getsysicon(icon):
icons = {
'stop': STOP,
'question': QUESTION,
'warning': WARNING,
'info': INFO
}

return icons.get(icon, NO_ICON)


def alert(
text="",
title="",
button=pymsgbox.OK_TEXT,
root=None,
timeout=None,
icon=NO_ICON,
icon=None,
_tkinter=False,
):
"""Displays a simple message box with text and a single OK button. Returns the text of the button clicked on."""
text = str(text)
if (_tkinter) or (timeout is not None) or (button != pymsgbox.OK_TEXT):
# Timeouts are not supported by Windows message boxes.
# Call the original tkinter alert function, not this native one:
return pymsgbox._alertTkinter(text, title, button, root, timeout)
return pymsgbox._alertTkinter(text, title, button, root, timeout, icon)

icon = _getsysicon(icon)
messageBoxFunc(0, text, title, MB_OK | MB_SETFOREGROUND | MB_TOPMOST | icon)
return button

Expand All @@ -76,7 +88,7 @@ def confirm(
buttons=(pymsgbox.OK_TEXT, pymsgbox.CANCEL_TEXT),
root=None,
timeout=None,
icon=QUESTION,
icon='question',
_tkinter=False,
):
"""Displays a message box with OK and Cancel buttons. Number and text of buttons can be customized. Returns the text of the button clicked on."""
Expand Down Expand Up @@ -114,8 +126,9 @@ def confirm(

if (_tkinter) or (timeout is not None) or (buttonFlag is None):
# Call the original tkinter confirm() function, not this native one:
return pymsgbox._confirmTkinter(text, title, buttons, root, timeout)
return pymsgbox._confirmTkinter(text, title, buttons, root, timeout, icon)

icon = _getsysicon(icon)
retVal = messageBoxFunc(
0, text, title, buttonFlag | MB_SETFOREGROUND | MB_TOPMOST | icon
)
Expand Down