📄 xmessagebox.cpp
字号:
// XMessageBox.cpp Version 1.5
//
// Author: Hans Dietrich
// hdietrich@gmail.com
//
// Description:
// XMessageBox.cpp implements XMessageBox(), a drop-in replacement for
// MessageBox() that includes custom checkboxes, custom buttons, custom
// icon, and more. For more information see
// http://www.codeproject.com/dialog/xmessagebox.asp
//
// History
// Version 1.5 - 2006 August 21
// - Fixed bugs reported by kingworm, TMS_73, Curtis Faith, ladislav Hruska,
// Tim Hodgson, DrJohnAir
// - Incorporated Uwe Keim's changes for dynamic button captions
//
// Version 1.4 - 2003 December 10
// - Implemented MB_DONOTSHOWAGAIN
// - Implemented MB_TOPMOST
// - Implemented MB_SETFOREGROUND
// - Added MB_SKIPSKIPALLCANCEL and MB_IGNOREIGNOREALLCANCEL, suggested
// by Shane L
// - Added HINSTANCE parameter for loading strings from extra-exe resource
// - Added "report function" parameter for optional report function
// - Added custom button parameter to allow definition of custom buttons,
// thanks to Obliterator for comments and review
// - Added timeout parameter to automatically select default button
// after timeout expires, thanks to Obliterator for suggestion
// - Added disabled time parameter, that will disable all buttons on the
// messagebox for n seconds (for nag dialogs).
// - Added custom icon parameter
// - The XMessageBox dialog will now be centered even in non-MFC apps,
// thanks to Tom Wright for suggestion
// - The message text and caption text can now be passed as either a string
// or a resource ID (using MAKEINTRESOURCE)
// - The initial x,y screen coordinates can now be specified.
// - The buttons can now be centered (default) or right-justified, as
// in XP Explorer.
// - Response to "Do Not Ask/Tell" checkboxes will be saved automatically
// to ini file, if lpszModule member is non-NULL
// - Gathered all optional parameters into one optional XMSGBOXPARAMS struct.
// - Added assert if default button is set to Help or Report button
// - Removed statics and rearranged code into classes, thanks to code from
// Anne Jan Beeks
//
// Version 1.3 - 2001 July 31
// - Miscellaneous improvements and bug fixes
//
// Version 1.2 - 2001 July 13
// - Initial public release
//
// Some parts of this software are from information in the Microsoft SDK.
//
// This software is released into the public domain. You are free to use it
// in any way you like, except that you may not sell this source code.
//
// This software is provided "as is" with no expressed or implied warranty.
// I accept no liability for any damage or loss of business that this software
// may cause.
//
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// include the following two lines if compiling an MFC app
#include "stdafx.h"
#pragma message(" compiling for MFC")
///////////////////////////////////////////////////////////////////////////////
#ifndef _MFC_VER
#include <windows.h>
#include <stdio.h>
#include <crtdbg.h>
#include <tchar.h>
#pragma message(" compiling for Win32")
#endif
#include "XMessageBox.h"
#pragma warning(disable : 4127) // conditional expression is constant
#pragma warning(disable : 4996) // disable bogus deprecation warning
#define countof(array) (sizeof(array)/sizeof(array[0]))
///////////////////////////////////////////////////////////////////////////////
//
// If you do not want TRACE output from XMessageBox.cpp you can
// uncomment the following lines:
//
//#undef TRACE
//#define TRACE ((void)0)
//
///////////////////////////////////////////////////////////////////////////////
//
// If you want to save the state of "Do Not Ask/Tell" checkbox to profile (ini)
// file instead of registry, uncomment the following line:
//
//#define XMESSAGEBOX_USE_PROFILE_FILE
///////////////////////////////////////////////////////////////////////////////
//
// If you do not want automatic saving of "Do Not Ask/Tell" checkbox,
// uncomment the following line:
//
//#define XMESSAGEBOX_DO_NOT_SAVE_CHECKBOX
///////////////////////////////////////////////////////////////////////////////
//
// If you have chosen to automatically save "Do Not Ask/Tell" checkbox to ini:
//
// Normally the lpszModule and nLine data are encoded, since it might not be
// desirable to allow users to be able to see the path and module name of
// your source file. If you do not want encoding of "Do Not Ask/Tell" module
// info in the registry (or ini file), uncomment the following line:
//
//#define XMESSAGEBOX_DO_NOT_ENCODE
///////////////////////////////////////////////////////////////////////////////
//
// This identifier specifies the format of the text displayed for the timeout
// key, which by default is "%s = %d". You may change this to anything you
// wish, as long as 1) there is both a %s and a %d; and 2) the %s precedes
// the %d.
//
#define XMESSAGEBOX_TIMEOUT_TEXT_FORMAT _T("%s = %d")
///////////////////////////////////////////////////////////////////////////////
//
// This identifier specifies the name of the ini file, which by default
// is "XMessageBox.ini".
//
#define XMESSAGEBOX_INI_FILE _T("XMessageBox.ini")
///////////////////////////////////////////////////////////////////////////////
//
// This identifier specifies the registry key used to store checkbox values.
// By default it is "XMessageBox".
//
#define XMESSAGEBOX_REGISTRY_KEY _T("XMessageBox")
#ifndef XMESSAGEBOX_USE_PROFILE_FILE
static void WriteRegistry(LPCTSTR lpszCompanyName, LPCTSTR lpszKey, DWORD dwData);
static DWORD ReadRegistry(LPCTSTR lpszCompanyName, LPCTSTR lpszKey);
#endif
///////////////////////////////////////////////////////////////////////////////
//
// CXRect - replacement for CRect
//
class CXRect : public tagRECT
{
public:
// Constructors
// uninitialized rectangle
CXRect() {}
// Attributes (in addition to RECT members)
// retrieves the width
int Width() const { return right - left; }
// returns the height
int Height() const { return bottom - top; }
// Operations
// set rectangle from left, top, right, and bottom
void SetRect(int x1, int y1, int x2, int y2)
{
::SetRect(this, x1, y1, x2, y2);
}
};
///////////////////////////////////////////////////////////////////////////////
//
// CXDialogItem
//
class CXDialogTemplate;
class CXDialogItem
{
public:
DLGITEMTEMPLATE m_dlgItemTemplate;
enum Econtroltype { ICON = 0x7F, BUTTON, EDITCONTROL, STATICTEXT, CHECKBOX };
Econtroltype m_controltype;
TCHAR * m_pszCaption; //+++1.5
public:
CXDialogItem(Econtroltype cType); // default constructor will fill in default values
CXDialogItem() {}; // default constructor, not to be called directly
virtual ~CXDialogItem(); //+++1.5
void AddItem(CXDialogTemplate& dialog,
Econtroltype cType,
UINT nID,
CXRect* prect = NULL,
LPCTSTR pszCaption = NULL);
};
///////////////////////////////////////////////////////////////////////////////
//
// CXDialogTemplate
//
class CXDialogTemplate
{
// Constructors
public:
CXDialogTemplate(HWND hWnd,
LPCTSTR lpszMessage,
LPCTSTR lpszCaption,
UINT nStyle,
XMSGBOXPARAMS *pXMB);
virtual ~CXDialogTemplate();
// Attributes
public:
LPCTSTR GetMessageText() const { return m_lpszMessage; }
int& GetButtonCount() { return m_nButton; }
UINT GetDefaultButtonId() const { return m_nDefId; }
void SetDefaultButtonId(UINT nDefId) { m_nDefId = nDefId; }
int GetDefaultButton() const { return m_nDefButton; }
// Operations
public:
int Display();
void AddItem(CXDialogItem::Econtroltype cType,
UINT nID,
CXRect* prect = NULL,
LPCTSTR pszCaption = NULL);
void AddCheckBox(HDC hdc,
int& x,
int& y,
CXRect& rect,
CXRect& mbrect,
CXRect& buttonrow,
CXRect& checkboxrect,
LPCTSTR lpszButtonCaption);
// Implementation
protected:
enum { FirstControlId = 1001};
enum { MaxButtonStringSize = 100};
enum
{
//ButtonWidth = 90,
ButtonWidth = 78, //+++1.5
ButtonTimeoutWidth = 100,
//ButtonHeight = 26,
ButtonHeight = 23, //+++1.5
ButtonSpacing = 6,
BottomMargin = 12,
DoNotAskAgainHeight = 16,
IdDoNotAskAgian = 5555,
IdExHelp = 300,
IdExReport = 301,
// if you change the value for MaxItems, make sure that the code
// in CXDialogTemplate remains consistent with your changes.
MaxItems = 20, // max no. of items in the dialog
MaxCustomButtons = 4,
MinimalHeight = 70,
SpacingSize = 8,
MessageSize = 64*1024,
SpacingBetweenMessageAndButtons = 10,
};
CXDialogItem* m_pDlgItemArray[MaxItems];
XMESSAGEBOX_REPORT_FUNCTION m_lpReportFunc;
DWORD m_dwReportUserData;
int m_Options;
int m_nButton; // current button no.
int m_nDefButton; // Default button
int m_nTimeoutSeconds; // timeout in seconds (before default button selected)
int m_nDisabledSeconds; // disabled time in seconds (before buttons are enabled)
int m_X, m_Y; // initial x,y screen coordinates
UINT m_nMaxID; // max control id (one more)
UINT m_nDefId; // button number of default button
UINT m_nHelpId; // help context id
UINT m_nStyle; // message box style
BOOL m_bRightJustifyButtons; // TRUE = right justify buttons
LPCTSTR m_lpszModule; // module name (for saving DoNotAsk state)
int m_nLine; // line number (for saving DoNotAsk state)
HWND m_hWnd; // handle of owner window
HINSTANCE m_hInstanceStrings; // handle to instance used for loading strings
HINSTANCE m_hInstanceIcon; // handle to instance used for loading icon
LPTSTR m_lpszMessage; // message buffer
LPTSTR m_lpszCaption; // caption buffer
TCHAR m_szCustomButtons[MAX_PATH]; // custom buttons - strings
// separated by \n
TCHAR m_szCompanyName[MAX_PATH]; // used when saving checkbox state in registry
HICON m_hIcon; // Handle of icon
HANDLE m_hFont; // handle to font for the message box
DLGTEMPLATE m_dlgTempl; // message box dialog template
TCHAR m_szDefaultButton [MaxButtonStringSize]; // used for original default
// button text, in case of
// countdown timer
TCHAR szAbort [MaxButtonStringSize];
TCHAR szCancel [MaxButtonStringSize];
TCHAR szContinue [MaxButtonStringSize];
TCHAR szDoNotAskAgain [MaxButtonStringSize];
TCHAR szDoNotTellAgain [MaxButtonStringSize];
TCHAR szDoNotShowAgain [MaxButtonStringSize];
TCHAR szHelp [MaxButtonStringSize];
TCHAR szIgnore [MaxButtonStringSize];
TCHAR szIgnoreAll [MaxButtonStringSize];
TCHAR szNo [MaxButtonStringSize];
TCHAR szNoToAll [MaxButtonStringSize];
TCHAR szOK [MaxButtonStringSize];
TCHAR szReport [MaxButtonStringSize];
TCHAR szRetry [MaxButtonStringSize];
TCHAR szSkip [MaxButtonStringSize];
TCHAR szSkipAll [MaxButtonStringSize];
TCHAR szTryAgain [MaxButtonStringSize];
TCHAR szYes [MaxButtonStringSize];
TCHAR szYesToAll [MaxButtonStringSize];
enum EOptions
{
DoNotAskAgain = 0x01, // include Do Not Ask checkbox
DoNotTellAgain = 0x02, // include Do Not Tell checkbox
DoNotShowAgain = 0x04, // include Do Not Show checkbox
CancelButton = 0x08, // include Cancel button
OkButton = 0x10, // MB_OK used
CancelOrOkButton = CancelButton | OkButton,
EDefault = 0x00
};
static BOOL CALLBACK MsgBoxDlgProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM me);
void Unset(EOptions id) { m_Options &= ~id;};
void Set(EOptions id) { m_Options |= id;};
int Option(EOptions id) const { return m_Options & id; }
void LoadButtonStrings();
void LoadButtonStringsFromResources(HINSTANCE hInstance);
//-[UK
void LoadUserDefinedButtonStrings(
const XMSGBOXPARAMS::CUserDefinedButtonCaptions& udcs );
//-]UK
};
#ifndef XMESSAGEBOX_DO_NOT_SAVE_CHECKBOX
///////////////////////////////////////////////////////////////////////////////
//
// encode()
//
// Purpose: Disguise string with simple encoding. Note that there is
// no requirement to decode string.
//
// Parameters: str - pointer null-terminated string to encode
//
// Returns: LPTSTR - pointer to str
//
#ifndef XMESSAGEBOX_DO_NOT_ENCODE
// folowing string MUST be at least 64 TCHARs
static TCHAR *szAlphabet = _T("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
_T("0123456789")
_T("abcdefghijklmnopqrstuvwxyz")
_T("98");
#endif
static LPTSTR encode(LPTSTR str)
{
#ifndef XMESSAGEBOX_DO_NOT_ENCODE
for (UINT i = 0; i < _tcslen(str); i++)
{
UINT n = (UINT) str[i];
str[i] = szAlphabet[(n + (5*i)) % 64];
}
#endif
return str;
}
#endif
///////////////////////////////////////////////////////////////////////////////
//
// XMessageBox()
//
// The XMessageBox function creates, displays, and operates a message box.
// The message box contains an application-defined message and title, plus
// any combination of predefined icons, push buttons, and checkboxes.
//
// For more information see
// http://www.codeproject.com/dialog/xmessagebox.asp
//
// int XMessageBox(HWND hwnd, // handle of owner window
// LPCTSTR lpszMessage, // address of text in message box
// LPCTSTR lpszCaption, // address of title of message box
// UINT nStyle, // style of message box
// XMSGBOXPARAMS * pXMB) // optional parameters
//
// PARAMETERS
//
// hwnd - Identifies the owner window of the message box to be
// created. If this parameter is NULL, the message box
// has no owner window.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -