How to Create a Custom Messagebox

How to create a custom MessageBox?

Your form class needs not to be static. In fact, a static class cannot inherit at all.

Instead, create an internal form class that derives from Form and provide a public static helper method to show it.

This static method may be defined in a different class if you don't want the callers to even “know” about the underlying form.

/// <summary>
/// The form internally used by <see cref="CustomMessageBox"/> class.
/// </summary>
internal partial class CustomMessageForm : Form
{
/// <summary>
/// This constructor is required for designer support.
/// </summary>
public CustomMessageForm ()
{
InitializeComponent();
}

public CustomMessageForm (string title, string description)
{
InitializeComponent();

this.titleLabel.Text = title;
this.descriptionLabel.Text = description;
}
}

/// <summary>
/// Your custom message box helper.
/// </summary>
public static class CustomMessageBox
{
public static void Show (string title, string description)
{
// using construct ensures the resources are freed when form is closed
using (var form = new CustomMessageForm (title, description)) {
form.ShowDialog ();
}
}
}

Side note: as Jalal points out, you don't have to make a class static in order to have static methods in it. But I would still separate the “helper” class from the actual form so the callers cannot create the form with a constructor (unless they're in the same assembly of course).

How to create custom messagebox?

You should not be calling mainloop inside the class. As a general rule of thumb you should only ever call mainloop() once the the life of the program. You already call it in the main logic after creating the root window so you shouldn't call it again.

Instead, you can use wait_window to wait until the window is destroyed before returning:

# Making MessageBox Visible
self.root.wait_window()

C# Custom Message Box that Returns Value OK or Cancel

I appreciate James' answer, however I wanted to post an answer that provides the full result of what I did to solve this problem to create a more functional custom message box tool.

See the code below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing;

namespace MyProgram
{
class CustomMessageBox
{
Label txtMsg = new Label();
Button btnOK = new Button();
Button btnCancel = new Button();
Form newForm = new Form();

private DialogResult spawnForm(string title, string text, MessageBoxButtons type)
{
if(type == MessageBoxButtons.OKCancel)
{
newForm.Text = title;
newForm.Controls.Add(txtMsg);
txtMsg.AutoSize = true;
txtMsg.Text = text;
newForm.Width = txtMsg.Width + 125;
newForm.Height = txtMsg.Height + 125;
newForm.MaximumSize = new Size(newForm.Width, newForm.Height);
newForm.MinimumSize = new Size(newForm.Width, newForm.Height);
txtMsg.Location = new Point(newForm.Width / 2 - txtMsg.Width / 2, newForm.Height / 2 - 40);
newForm.Controls.Add(btnOK);
newForm.Controls.Add(btnCancel);
btnOK.Text = "OK";
btnCancel.Text = "Cancel";

btnOK.Location = new Point(newForm.Width / 2 - btnOK.Width / 2 - 60, txtMsg.Location.Y + txtMsg.Height + 20);
btnCancel.Location = new Point(newForm.Width / 2 - btnOK.Width / 2 + 40, btnOK.Location.Y);
btnOK.DialogResult = DialogResult.OK;
btnCancel.DialogResult = DialogResult.Cancel;
newForm.StartPosition = FormStartPosition.CenterParent;
return newForm.ShowDialog();
} else
{
newForm.Text = title;
newForm.Controls.Add(txtMsg);
txtMsg.AutoSize = true;
txtMsg.Text = text;
newForm.Width = txtMsg.Width + 125;
newForm.Height = txtMsg.Height + 125;
newForm.MaximumSize = new Size(newForm.Width, newForm.Height);
newForm.MinimumSize = new Size(newForm.Width, newForm.Height);
txtMsg.Location = new Point(newForm.Width / 2 - txtMsg.Width / 2 - 10, newForm.Height / 2 - 40);
newForm.Controls.Add(btnOK);
newForm.Controls.Remove(btnCancel);
btnOK.Text = "OK";
btnOK.Location = new Point(newForm.Width / 2 - btnOK.Width / 2 -10, txtMsg.Location.Y + txtMsg.Height + 20);
btnOK.DialogResult = DialogResult.OK;
newForm.StartPosition = FormStartPosition.CenterParent;
return newForm.ShowDialog();
}
}

public DialogResult Text(string title, string text, MessageBoxButtons type)
{
return spawnForm(title, text, type);
}
}
}

How I create custom button in a messagebox in .net form application?

If you are after a messagebox with ok and cancel buttons you can use

 MessageBox.Show(this, "Message", "caption", MessageBoxButtons.OKCancel);

If you want a custom look/feel and any buttons that you don't normally see on messageboxes, then you have to make your own form to display

MessageBoxButton options

Python Tk : How to create a custom message box

I solved it myself.

I'm binding mouse events for custom dialog navigation.
Therefore, after Destroy was called, the dialog with the mouse release event discarded was notified and an error occurred.

To solve this, I made self.isDestroy, and in the btn_msgbox_clicked method, changed self.isDestroy to True and connected the dialog_mouse_release method to the destroy method.

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import tkinter as tk
from tkinter import ttk

from tkinter import messagebox

from PIL import Image,ImageTk,ImageDraw,ImageFont

import datetime

class CustomDialog(object):
def __init__(self):

self.title_bar_color = '#8FAADC'
self.item_ground_color = 'whitesmoke'
self.background_color = '#D9D9D9'
self.select_bar_color = '#BDD7EE'

self.isDrag_DlgMotion = False
self.drag_dx = 0
self.drag_dy = 0

def dialog_left_click(self,event):
dialog_x=self.dev_dialog.winfo_rootx()
dialog_y=self.dev_dialog.winfo_rooty()
point_x=self.dev_dialog.winfo_pointerx()
point_y=self.dev_dialog.winfo_pointery()

dx = point_x - dialog_x
dy = point_y - dialog_y

if (dx >= 0 and dx <= self.title_bar_width) and (dy >= 0 and dy <= self.title_bar_height):
self.drag_dx = dx
self.drag_dy = dy
self.isDrag_DlgMotion = True
return

def dialog_mouse_move_on(self,event):
if self.isDrag_DlgMotion:
X = event.x_root - self.drag_dx
Y = event.y_root - self.drag_dy
self.dev_dialog.geometry('+{0}+{1}'.format(X, Y))
pass
return

def dialog_mouse_release(self,event):
if self.isDrag_DlgMotion:
self.isDrag_DlgMotion = False
return

class CommonMessageBoxDialog(CustomDialog):
def __init__(self,title,message,state,parent = None):
self.return_state = None
self.isDestroy = False

if not isinstance(title,str) or not isinstance(message,str) or not isinstance(state,int):
return
if state < 1 or state > 3 :
return

root = ttk.tkinter.Tk()

#root = tk.Toplevel(parent)
#root.overrideredirect(True)

super().__init__()

self.box_state = state
self.box_message = message
self.box_title = title

W = 0
H = 1

self.dlg_size = [400,200]

self.title_bar_width = self.dlg_size[W]
self.title_bar_height = 40

self.btn_bar_height = 42

self.btn_32x32_size = 42

self.row_height = 28
self.btn_row_height = 32

self.frm_space = 10

self.parent = parent
self.CreateDialog(root)

root.wait_window(root)

#root.mainloop()

def CreateDialog(self,root):

W = 0
H = 1

if self.parent != None:
self.parent.update_idletasks()
ww=self.parent.winfo_screenwidth()
wh=self.parent.winfo_screenheight()
x=self.parent.winfo_rootx()
y=self.parent.winfo_rooty()

parent_w = self.parent.winfo_width()
parent_h = self.parent.winfo_height()
parent_x = self.parent.winfo_x()
parent_y = self.parent.winfo_y()
else:
root.update_idletasks()
ww=root.winfo_screenwidth()
wh=root.winfo_screenheight()
x=root.winfo_rootx()
y=root.winfo_rooty()

parent_w = root.winfo_width()
parent_h = root.winfo_height()
parent_x = root.winfo_x()
parent_y = root.winfo_y()

self.dev_dialog = root
dialog = self.dev_dialog
dialog.overrideredirect(True)

dlg_x = int((parent_x+parent_w) - (self.dlg_size[W]/2))
dlg_y = int((parent_y+parent_h) - (self.dlg_size[H]/2))

if dlg_x < 0 : dlg_x = 0
if dlg_y < 0 : dlg_y = 0

dialog.geometry('{}x{}+{}+{}'.format(self.dlg_size[W],self.dlg_size[H],dlg_x,dlg_y))

self.Title_Bar = tk.Frame(
dialog,
relief='flat',
bg = self.title_bar_color ,
)
self.Title_Label = tk.Label(
self.Title_Bar,
bg = self.title_bar_color ,
text = self.box_title,
)

dialog.bind('<Button-1>', self.dialog_left_click)
dialog.bind('<B1-Motion>', self.dialog_mouse_move_on)
dialog.bind('<ButtonRelease-1>',self.dialog_mouse_release)

self.MsgArea_frame = tk.Frame(
dialog,
relief='flat',
bg = self.select_bar_color,
)
self.message_frame = tk.Frame(
self.MsgArea_frame,
relief='flat',
bg = self.item_ground_color ,
)
self.label_message = tk.Label(
self.message_frame,
bg = self.item_ground_color ,
text = self.box_message,
)

self.BtnArea_frame = tk.Frame(
dialog,
relief='flat',
bg = self.item_ground_color,
)

self.btn_ok = tk.Button(
self.BtnArea_frame,
bg = self.item_ground_color,
text = 'OK',
command = lambda:self.btn_msgbox_clicked(1),
)

self.btn_yes = tk.Button(
self.BtnArea_frame,
bg = self.item_ground_color,
text = 'YES',
command = lambda:self.btn_msgbox_clicked(1),
)

self.btn_no = tk.Button(
self.BtnArea_frame,
bg = self.item_ground_color,
text = 'NO',
command = lambda:self.btn_msgbox_clicked(2),
)

self.btn_cancel = tk.Button(
self.BtnArea_frame,
bg = self.item_ground_color,
text = 'CANCEL',
command = lambda:self.btn_msgbox_clicked(3),
)

frm_space = self.frm_space
msg_frm_w = 4
btn_fram_h = 36

message_area_h = self.dlg_size[H] - self.title_bar_height - frm_space *2 - btn_fram_h

# Frame
self.Title_Bar.place(
x = 0, y = 0,
width = self.title_bar_width, height = self.title_bar_height
)
self.MsgArea_frame.place(
x = frm_space, y = self.title_bar_height + frm_space,
width = self.title_bar_width - frm_space*2, height = message_area_h
)
self.BtnArea_frame.place(
x = 0, y = self.title_bar_height + frm_space + message_area_h,
width = self.title_bar_width, height = btn_fram_h
)

self.Title_Label.grid(row = 0, column = 1,sticky = tk.W+tk.N+tk.S)
self.Title_Bar.columnconfigure(0,minsize = self.frm_space)
self.Title_Bar.rowconfigure(0,minsize = self.title_bar_height)

self.MsgArea_frame.columnconfigure(0,minsize = self.frm_space)
self.MsgArea_frame.rowconfigure(0,minsize = message_area_h)

self.BtnArea_frame.rowconfigure(0,minsize = btn_fram_h)

self.message_frame.place(
x = msg_frm_w, y = msg_frm_w,
width = self.title_bar_width - frm_space*2 - msg_frm_w*2, height = message_area_h - msg_frm_w*2,
)

# self.message_frame
self.label_message.grid(row = 0, column = 1,sticky = tk.W+tk.N+tk.S)

if self.box_state == 1:
self.btn_ok.place(
x = (self.title_bar_width/2) - 80/2 , y = btn_fram_h/2 - 24/2,
)
if self.box_state == 2:
self.btn_yes.place(
x = (self.title_bar_width/2) - (80 + frm_space) , y = btn_fram_h/2 - 24/2,
)
self.btn_no.place(
x = (self.title_bar_width/2) + frm_space , y = btn_fram_h/2 - 24/2,
)
if self.box_state == 3:
self.btn_yes.place(
x = (self.title_bar_width/2) - (80*1.5 + frm_space*2) , y = btn_fram_h/2 - 24/2,
)
self.btn_no.place(
x = (self.title_bar_width/2) - 80/2 , y = btn_fram_h/2 - 24/2,
)
self.btn_cancel.place(
x = (self.title_bar_width/2) + 80/2 + frm_space*2 , y = btn_fram_h/2 - 24/2,
)

#dialog.grab_set()
dialog.grab_set_global()

def btn_msgbox_clicked(self,state):
self.return_state = state
self.isDestroy = True

def get_return_state(self):
return self.return_state

def dialog_mouse_release(self,event):
if self.isDrag_DlgMotion:
self.isDrag_DlgMotion = False

if self.isDestroy:
self._quit()
return

def _quit(self):
self.dev_dialog.grab_release()
self.dev_dialog.destroy()

class CreateScreen(object):
def __init__(self):
self.cnt = 0
W = 0
H = 1
self.dlg_size = [400,200]

geo_string = '{}x{}'.format(self.dlg_size[W],self.dlg_size[H])

self.MainWindow_obj = ttk.tkinter.Tk()
self.MainWindow_obj.geometry(geo_string)

self.CntSting = tk.StringVar()
self.CntSting.set(str(self.cnt))

Label_Conter_text = tk.Label(
self.MainWindow_obj,
textvariable = self.CntSting,
)

self.MsgSting = tk.StringVar()
self.MsgSting.set('...')

Label_Message_text = tk.Label(
self.MainWindow_obj,
textvariable = self.MsgSting,
)

Btn_Messagebox = tk.Button(
self.MainWindow_obj,
text = 'Push',
command = self.Btn_Messagebox_clicked
)
Label_Conter_text.pack()
Label_Message_text.pack()
Btn_Messagebox.pack()

self.MainWindow_obj.after(1000,self.loop_msg)

self.MainWindow_obj.mainloop()

def Btn_Messagebox_clicked(self):
self.dlg = CommonMessageBoxDialog(title='Test',message='Do you remember ?',state=3,parent =self.MainWindow_obj)
ret = self.dlg.get_return_state()

if ret == 1:
self.MsgSting.set('Yes')
if ret == 2:
self.MsgSting.set('No')
if ret == 3:
self.MsgSting.set('Cancel')

return

def loop_msg(self):
self.cnt += 1
self.CntSting.set(str(self.cnt))

self.MainWindow_obj.after(1000,self.loop_msg)

if __name__ == '__main__':
screen_obj = CreateScreen()

Creating a custom MessageBox class for MFC

There is some design issues here, for this type of interface the program should save automatically. If user is deleting the file then confirm it with modeless dialog. This way data is not lost if user is impatient. Anyway, you can just override OnPaint etc. and draw the icon

void CMyDlg::OnPaint()
{
CDialog::OnPaint();
//draw white rectangle on top-half of dialog
//draw lt-gray rectangle at bottom-half, GetSysColor(COLOR_BTNFACE)
HICON hIcon = LoadIcon(NULL, IDI_ERROR);
dc.DrawIcon(x, y, hIcon);
DestroyIcon(hIcon);
}

BOOL CMyDlg::OnEraseBkgnd(CDC* pDC)
{
return 1;
}

You might also need to override OnCtlColor



Related Topics



Leave a reply



Submit