With Windows Hook and some other Win32 APIs, you can use the system.windows.forms.MessageBox to use to achieve some cool results. This example implements how to add a timer to System.Windows.Forms.MessageBox. The development impulse of this example comes from Lianzhong Flying Chess. Many friends think it is not easier to use System.Windows.Forms.form multi-threaded, unfortunately - my point of view is the opposite. Developing advanced WinForm applications on .NET, (at least until now) Traditional Win32 API is unavoidable, many advanced applications and techniques must be used to use Win32 API. It is better to face with it, it is better to face it. This article does not introduce the principles and C # implementation of Windows Hook, please refer to: http://msdn.microsoft.com/msdnmag/issues/02/10/cuttingEDGE/ (About Windows Hook details, this example uses Class) http://msdn.microsoft.com/msdnmag/issues/02/11/CuttingEDGE/ (About MessageBox other surgery improvements) Before reading this text, please read the above two. This article does not introduce the principle about the C # call of Win32 API. Some Win32 enumerations referred to in the text and a large number of Win32 API come from my personal standard Win32 library (especially WindowsAPI tool class). Most methods and enumeration names are consistent with the name of MSDN, which can be said to be an eye. The specific implementation code is as follows, and the technical details of the implementation are inclusions between the code, and there is no more expensive tongue here. Finally, it is necessary to declare that this example has just been released, so it has not been tested on Windows 98. Using system.drawing; using system.windows.forms ;. USING SYSTEM.WINDOWING;
Using XXXX.COMMON.WIN32;
Namespace xxxx.library.Forms {/// /// //// TIMABLEMESSAGEBOX TMMSGBOX = New TimableMessageBox (); /// TMMSGBOX.DELAYSECONDS = 15; // The default is 10 second SECONDS. /// // TMMSGBOX.CUSOTMICON = YOURICON / / can set the custom icon here. /// DialogResult DR; /// DR = TMMSGBOX.SHOW (DialogResult.no, // After the default result /// "Your message text", /// "Your Title", ////////////////////////////////////////////////////////////////////// /// MessageBoxicon.question; /// // IF (DR == DialogResult.no) /// Return; /// else //// DO Your process ... ///// < / code> /// example> public class timableMessageBox {// A default clock icon (shown in the diagram) // A icon from this assembly is subject to an icon // will not introduce how to set up and read embedded resources private static Icon DefaultIcon = Resources.icoTimer01; // define a static text control style private const int StaticTextControlStyle = (int) StaticStyles.SS_CENTER | (int) WindowStyles.WS_CHILD | (int) WindowStyles.WS_VISIBLE; // Win32 constant private const int ID_ICONWINDOW = 0x0014; private const int STM_SETICON = 0x0170; // variable domain protected LocalCbtHook m_cbt; protected IntPtr m_hwnd = IntPtr.Zero; protected IntPtr m_hwndStatic = IntPtr.Zero; protected IntPtr m_closeButton = IntPtr.Zero; protected bool m_bInited = false; protected bool m_btimeout = false; protected bool m_iscustom = false; Protected bool m_needenumchild = false; protected bool m_needreplaceicon = false; protected iCON m_custom; private int m_timercount = 0; private int m_delaysecond = 10;
///
///
Private void WNDCREATED (Object sender, cbteventargs e) {if (e.Isdialogwindow) {m_binited = false; m_hwnd = E.handle;}}
Private Void Wndactivated (Object Sender, CBTEventArgs E) {// is not the same window does not process if (m_hwnd! = E.handle) return;
// Whether it has been initialized, the subsequent changes are required only when the message frame is activated. if (m_bInited) return; else m_bInited = true; // replacement icon if (m_needReplaceIcon) {IntPtr hwndIcon1 = WindowsAPI.GetDlgItem (m_hwnd, ID_ICONWINDOW); IntPtr hIcon; if (m_isCustom) {hIcon = m_customIcon.Handle;} else {hIcon = Defaulticon.handle;} Windowsapi.sendMessage (HWndicon1, STM_SETICON, HICON, INTPTR.ZERO);}
#Region Add a static text control
/ / Get the font that can be used by static text controls. IntPtr hFont; IntPtr hwndText = WindowsAPI.GetDlgItem (m_hwnd, 0xFFFF); if (! HwndText = IntPtr.Zero) hFont = new IntPtr (WindowsAPI.SendMessage (hwndText, (int) Msg.WM_GETFONT, IntPtr.Zero, IntPtr.Zero) ); Else hfont = new intptr (windowsapi.sendMessage (m_hWnd, (int) msg.wm_getfont, intptr.zero, intptr.zero); font fcur = font.fromhfont (hfont); // Get x X of a static text control location And Y coordinate value int x = 0, y = 0; INTPTR hWndicon = Windowsapi.getdlgitem (m_hwnd, id_iconwindow); Rect RCICON = new Rect (); Windowsapi.GetWindower; Point Pt = New Point () Pt.x = rcicon.top; pt.y = rcicon.top; windowsapi.screenToclient (m_hwnd, ref pt); x = pt.x; y = pt.y rCICION.BOTTOM - RCICON.TOP 2;
// Create a static text control and add to the message box m_hwndstatic = Windowsapi.createWindowex (0, "static", "0", statictextcontrolstyle, x, y, rCICON.RIGHT - RCICON.LEFT, (int) fcur.getHeight () , M_HWND, INTPTR.ZERO, INTPTR.ZERO, INTPTR.ZERO;
/ / Update the required font windowsapi.sendMessage (m_hWndStatic, (int) msg.wm_setfont, hfont, new intptr (1)); // find the button IF on a message box if (m_needenumchild) Windowsapi.EnumChildWindows (this.m_hwnd, New Windowsapi.enumChildProc (this.enumchildWindowsProc), 0);
// Remove hook m_cbt.uninstall (); #ndregion}
/ / Time information Update Timer's Process Routor Private Void TimerupdateElapseHandler (INTPTR HWND, UINT UIMSG, UINT IDEVENT, INT DWTIME) {IF (this.m_hwndstatic == INTPTR.ZERO) Return;
// Display Time Message Text Windowsapi.SetWindowText (this.m_hwndstatic, ( m_timercount) .tostring ());}
// Close message box timer processing routine private void TimerCloseElapseHandler (IntPtr hWnd, uint uiMsg, uint idEvent, int dwTime) {// need to simulate a click operation if (m_closeButton! = IntPtr.Zero) {int buttonCommand = WindowsAPI .GetDlgCtrlID (m_closeButton); // Console.WriteLine:; // send a command message WindowsAPI.SendMessage (m_hwnd, (int) Msg.WM_COMMAND, buttonCommand, m_closeButton);} else {// sent directly ( "command" buttonCommand) Close window message Windowsapi.sendMessage (m_hwnd, (uint) msg.wm_close, 0, 0);} // Setting the timeout tag m_btimeout = true;} // The process routine // is used to find a button. Private Bool EnumchildWindowsProc (intptr hwnd, int lpram) {// Gets the Windows Class name of the sub-window. StringBuffer Sb; int Lret = Windowsapi.getClassName (hwnd, out sb, 512); string sclassname = sb.sztext; //console.writeline(SClassName);
/ / Check if it is a button. IF (SclassName.toupper () == "Button") {m_closebutton = hwnd; return false; // Just start to stop enumeration} else {return true;}} #Region methods ///
// If you do not specify an icon type, add a placeholder icon type. // As long as MessageBoxicon.none can, // But pay attention to Warning, Stop, Error will send a different sound. / / Make sure there is an icon, which is to display timing information below the icon. IF (icon == MessageBoxicon.none) {icon = messageboxicon.information;} // Reset each marker M_BTIMEOUT = false; m_timercount = 0; m_hwnd = INTPTR.ZERO; m_closebutton = INTPTR.ZERO; // Due to two The close button on the window title bar of the button style is disabled, // The sending WM_CLOSE message is sent to the message box at this time. // So use a roundabout method: first find any button on the message box, // In the event handling routine of the closing message frame timer, the button simulates a command operation, // to achieve the purpose of the closing window . As the button is not important, because the timeout returned // dialog assembly is the default value parameter set by the caller: TimeoutDialogresutl. M_needenumchild = (MessageBoxButtons.AbortRetryIgnore == Buttons || messageboxbuttons.yesno == Buttons);
// Create two timer // Close the timer INTPTR TIMERCOLSE = WindowsApi.SetTim (INTPTR.ZERO, 0, M_DELAYSECOND * 1000, New WindowsApi.TimerPSehandler); // Update Timer INTPTR Timerupdate = Windowsapi.Settimer (INTPTR.ZERO, 0, 1000, New Windowsapi.TimerProc (TimerUpdateElapseHandler);
/ / Set hook m_cbt.install ();
// Display message box DialogResult Dr = MessageBox.Show (StrMessageText, StrMessageboXtitle, Buttons, Icon, DefaultButton);
// Destroy Timer Windowsapi.killTimer (INTPTR.ZERO, TIMERCOLSE); Windowsapi.killTimer (INTPTR.ZERO, TIMERUPDATE);
/ / The corresponding result is returned to the corresponding result. If (m_btimeout) return timeoutdialogresult; // If you turn, return the value set by the parameter. ELSE RETURN DR; // If there is no timeout, the value of the user clicks is returned. }
public DialogResult Show (DialogResult timeoutDialogResult, string strMessageText, string strMessageBoxTitle, System.Windows.Forms.MessageBoxButtons buttons, MessageBoxIcon icon) {return Show (timeoutDialogResult, strMessageText, strMessageBoxTitle, buttons, icon, MessageBoxDefaultButton.Button1);} public DialogResult Show (DialogResult timeoutDialogResult, string strMessageText, string strMessageBoxTitle, System.Windows.Forms.MessageBoxButtons buttons) {return Show (timeoutDialogResult, strMessageText, strMessageBoxTitle, buttons, MessageBoxIcon.None);} public DialogResult Show (DialogResult timeoutDialogResult, string strMessageText, string strMessageBoxTitle) {return show (timeoutDialogResult, strMessageText, strMessageBoxTitle, System.Windows.Forms.MessageBoxButtons.OK);} public DialogResult show (DialogResult timeoutDialogResult, string strMessageText) {return show (timeoutDialogResult, strMessageText, "");}
#ndregion}}}