.Net下Winform程序让MessageBox.Show显示在父窗体中间

本文介绍了如何通过自定义消息框类实现窗口激活时的居中显示功能,包括初始化、消息处理和窗口位置调整等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. using System;  
  2. using System.Windows.Forms;  
  3. using System.Text;  
  4. using System.Drawing;  
  5. using System.Runtime.InteropServices;  
  6.   
  7.   
  8. public class MessageBoxEx  
  9. {  
  10.     private static IWin32Window _owner;  
  11.     private static HookProc _hookProc;  
  12.     private static IntPtr _hHook;  
  13.   
  14.     public static DialogResult Show(string text)  
  15.     {  
  16.         Initialize();  
  17.         return MessageBox.Show(text);  
  18.     }  
  19.   
  20.     public static DialogResult Show(string text, string caption)  
  21.     {  
  22.         Initialize();  
  23.         return MessageBox.Show(text, caption);  
  24.     }  
  25.   
  26.     public static DialogResult Show(string text, string caption, MessageBoxButtons buttons)  
  27.     {  
  28.         Initialize();  
  29.         return MessageBox.Show(text, caption, buttons);  
  30.     }  
  31.   
  32.     public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)  
  33.     {  
  34.         Initialize();  
  35.         return MessageBox.Show(text, caption, buttons, icon);  
  36.     }  
  37.   
  38.     public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton)  
  39.     {  
  40.         Initialize();  
  41.         return MessageBox.Show(text, caption, buttons, icon, defButton);  
  42.     }  
  43.   
  44.     public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options)  
  45.     {  
  46.         Initialize();  
  47.         return MessageBox.Show(text, caption, buttons, icon, defButton, options);  
  48.     }  
  49.   
  50.     public static DialogResult Show(IWin32Window owner, string text)  
  51.     {  
  52.         _owner = owner;  
  53.         Initialize();  
  54.         return MessageBox.Show(owner, text);  
  55.     }  
  56.   
  57.     public static DialogResult Show(IWin32Window owner, string text, string caption)  
  58.     {  
  59.         _owner = owner;  
  60.         Initialize();  
  61.         return MessageBox.Show(owner, text, caption);  
  62.     }  
  63.   
  64.     public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons)  
  65.     {  
  66.         _owner = owner;  
  67.         Initialize();  
  68.         return MessageBox.Show(owner, text, caption, buttons);  
  69.     }  
  70.   
  71.     public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)  
  72.     {  
  73.         _owner = owner;  
  74.         Initialize();  
  75.         return MessageBox.Show(owner, text, caption, buttons, icon);  
  76.     }  
  77.   
  78.     public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton)  
  79.     {  
  80.         _owner = owner;  
  81.         Initialize();  
  82.         return MessageBox.Show(owner, text, caption, buttons, icon, defButton);  
  83.     }  
  84.   
  85.     public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options)  
  86.     {  
  87.         _owner = owner;  
  88.         Initialize();  
  89.         return MessageBox.Show(owner, text, caption, buttons, icon,  
  90.                                defButton, options);  
  91.     }  
  92.   
  93.     public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);  
  94.   
  95.     public delegate void TimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime);  
  96.   
  97.     public const int WH_CALLWNDPROCRET = 12;  
  98.   
  99.     public enum CbtHookAction : int  
  100.     {  
  101.         HCBT_MOVESIZE = 0,  
  102.         HCBT_MINMAX = 1,  
  103.         HCBT_QS = 2,  
  104.         HCBT_CREATEWND = 3,  
  105.         HCBT_DESTROYWND = 4,  
  106.         HCBT_ACTIVATE = 5,  
  107.         HCBT_CLICKSKIPPED = 6,  
  108.         HCBT_KEYSKIPPED = 7,  
  109.         HCBT_SYSCOMMAND = 8,  
  110.         HCBT_SETFOCUS = 9  
  111.     }  
  112.   
  113.     [DllImport("user32.dll")]  
  114.     private static extern bool GetWindowRect(IntPtr hWnd, ref Rectangle lpRect);  
  115.   
  116.     [DllImport("user32.dll")]  
  117.     private static extern int MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);  
  118.   
  119.     [DllImport("User32.dll")]  
  120.     public static extern UIntPtr SetTimer(IntPtr hWnd, UIntPtr nIDEvent, uint uElapse, TimerProc lpTimerFunc);  
  121.   
  122.     [DllImport("User32.dll")]  
  123.     public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);  
  124.   
  125.     [DllImport("user32.dll")]  
  126.     public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);  
  127.   
  128.     [DllImport("user32.dll")]  
  129.     public static extern int UnhookWindowsHookEx(IntPtr idHook);  
  130.   
  131.     [DllImport("user32.dll")]  
  132.     public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);  
  133.   
  134.     [DllImport("user32.dll")]  
  135.     public static extern int GetWindowTextLength(IntPtr hWnd);  
  136.   
  137.     [DllImport("user32.dll")]  
  138.     public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxLength);  
  139.   
  140.     [DllImport("user32.dll")]  
  141.     public static extern int EndDialog(IntPtr hDlg, IntPtr nResult);  
  142.   
  143.     [StructLayout(LayoutKind.Sequential)]  
  144.     public struct CWPRETSTRUCT  
  145.     {  
  146.         public IntPtr lResult;  
  147.         public IntPtr lParam;  
  148.         public IntPtr wParam;  
  149.         public uint message;  
  150.         public IntPtr hwnd;  
  151.     } ;  
  152.   
  153.     static MessageBoxEx()  
  154.     {  
  155.         _hookProc = new HookProc(MessageBoxHookProc);  
  156.         _hHook = IntPtr.Zero;  
  157.     }  
  158.   
  159.     private static void Initialize()  
  160.     {  
  161.         if (_hHook != IntPtr.Zero)  
  162.         {  
  163.             throw new NotSupportedException("multiple calls are not supported");  
  164.         }  
  165.   
  166.         if (_owner != null)  
  167.         {  
  168.             _hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, _hookProc, IntPtr.Zero, AppDomain.GetCurrentThreadId());  
  169.         }  
  170.     }  
  171.   
  172.     private static IntPtr MessageBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam)  
  173.     {  
  174.         if (nCode < 0)  
  175.         {  
  176.             return CallNextHookEx(_hHook, nCode, wParam, lParam);  
  177.         }  
  178.   
  179.         CWPRETSTRUCT msg = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));  
  180.         IntPtr hook = _hHook;  
  181.   
  182.         if (msg.message == (int)CbtHookAction.HCBT_ACTIVATE)  
  183.         {  
  184.             try  
  185.             {  
  186.                 CenterWindow(msg.hwnd);  
  187.             }  
  188.             finally  
  189.             {  
  190.                 UnhookWindowsHookEx(_hHook);  
  191.                 _hHook = IntPtr.Zero;  
  192.             }  
  193.         }  
  194.   
  195.         return CallNextHookEx(hook, nCode, wParam, lParam);  
  196.     }  
  197.   
  198.     private static void CenterWindow(IntPtr hChildWnd)  
  199.     {  
  200.         Rectangle recChild = new Rectangle(0, 0, 0, 0);  
  201.         bool success = GetWindowRect(hChildWnd, ref recChild);  
  202.   
  203.         int width = recChild.Width - recChild.X;  
  204.         int height = recChild.Height - recChild.Y;  
  205.   
  206.         Rectangle recParent = new Rectangle(0, 0, 0, 0);  
  207.         success = GetWindowRect(_owner.Handle, ref recParent);  
  208.   
  209.         Point ptCenter = new Point(0, 0);  
  210.         ptCenter.X = recParent.X + ((recParent.Width - recParent.X) / 2);  
  211.         ptCenter.Y = recParent.Y + ((recParent.Height - recParent.Y) / 2);  
  212.   
  213.         Point ptStart = new Point(0, 0);  
  214.         ptStart.X = (ptCenter.X - (width / 2));  
  215.         ptStart.Y = (ptCenter.Y - (height / 2));  
  216.   
  217.         ptStart.X = (ptStart.X < 0) ? 0 : ptStart.X;  
  218.         ptStart.Y = (ptStart.Y < 0) ? 0 : ptStart.Y;  
  219.   
  220.         int result = MoveWindow(hChildWnd, ptStart.X, ptStart.Y, width, height, false);  
  221.     }  
  222. }  


  1. 调用方式:
  1. DialogResult dr = MessageBoxEx.Show(this,"是否要删除此数据?""删除确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Information, MessageBoxDefaultButton.Button2);  
  2.   
  3. if (dr == DialogResult.Cancel)  
  4. {  
  5.     return;  
  6. }  


转自:http://blog.youkuaiyun.com/aspnet2002web/article/details/28173289
<think>好的,用户现在想在.NET4.6中使用MaterialSkin来自定义WinFormMessageBox样式,并且解决之前遇到的lblMessage.Text未声明的问题。我需要先回顾之前的对话,确保这次回答能覆盖所有要点。首先,用户之前提到lblMessage.Text未声明的问题,我之前给出的解决方案是检查设计器是否添加了控件,命名是否正确,以及是否继承正确的控件类型。现在用户进一步希望将MaterialSkin应用到MessageBox上,所以需要结合这两个需求。用户参考了站内引用,其中提到让MessageBox显示父窗体中间,以及按钮和图标样式的使用。但用户的实际需求是自定义MessageBox的样式,而原生的MessageBox无法直接修改,所以需要创建自定义窗体来模拟MessageBox的行为。接下来,我需要分步骤说明如何创建自定义的MaterialMessageBox窗体,使用MaterialSkin控件替换原生控件,并确保正确声明和引用lblMessage。需要包括添加MaterialLabel控件、设置属性、初始化代码以及显示对话框的方法。 同时,要解决lblMessage.Text未声明的问题,必须确保设计器文件中正确生成了控件的声明和初始化,并且在代码中正确引用。可能需要指导用户检查Designer.cs文件,或者手动添加控件声明。 另外,用户可能遇到的常见问题包括控件未正确继承MaterialSkin的样式,或者事件处理不正确,比如关闭按钮的逻辑。需要提醒用户在主窗体中初始化MaterialSkinManager,以确保样式一致。最后,生成的相关问题需要围绕MaterialSkin的使用和自定义窗体展开,例如如何添加图标、处理长文本、动画效果等。确保问题与当前主题相关,帮助用户深入理解。</think>### 解决方案:在.NET 4.6中使用MaterialSkin自定义WinForm MessageBox样式 --- #### 一、问题分析 1. **原生MessageBox限制** - 原生`MessageBox`无法直接应用MaterialSkin样式 - 需要创建自定义窗体`MaterialMessageBox`来模拟标准对话框行为[^1] 2. **lblMessage.Text未声明问题** - 未正确声明`MaterialLabel`控件 - 设计器文件未正确生成控件初始化代码 --- #### 二、实现步骤 ##### 1. 创建自定义窗体类 ```csharp using MaterialSkin; using MaterialSkin.Controls; public partial class MaterialMessageBox : MaterialForm { // 声明MaterialLabel控件 private MaterialLabel lblMessage; private MaterialButton btnOK; private MaterialButton btnCancel; } ``` ##### 2. 设计器配置(MaterialMessageBox.Designer.cs) ```csharp private void InitializeComponent() { this.lblMessage = new MaterialSkin.Controls.MaterialLabel(); this.btnOK = new MaterialSkin.Controls.MaterialButton(); this.btnCancel = new MaterialSkin.Controls.MaterialButton(); // 标签配置 this.lblMessage.AutoSize = false; this.lblMessage.Depth = 0; this.lblMessage.Dock = DockStyle.Fill; this.lblMessage.Font = new Font("微软雅黑", 11F); this.lblMessage.Location = new Point(10, 80); this.lblMessage.Size = new Size(380, 120); // 按钮配置 this.btnOK.DialogResult = DialogResult.OK; this.btnCancel.DialogResult = DialogResult.Cancel; } ``` ##### 3. 构造函数与初始化 ```csharp public MaterialMessageBox(string text, string caption, MessageBoxButtons buttons) { InitializeComponent(); // 应用MaterialSkin主题 var materialSkinManager = MaterialSkinManager.Instance; materialSkinManager.AddFormToManage(this); materialSkinManager.Theme = MaterialSkinManager.Themes.LIGHT; // 设置控件属性 this.Text = caption; lblMessage.Text = text; // 确保控件已正确初始化 // 动态创建按钮布局 switch (buttons) { case MessageBoxButtons.OKCancel: btnOK.Text = "确定"; btnCancel.Text = "取消"; break; case MessageBoxButtons.YesNo: btnOK.Text = "是"; btnCancel.Text = "否"; break; } } ``` ##### 4. 显示对话框方法 ```csharp public static DialogResult Show(string text, string caption, MessageBoxButtons buttons) { using (var dialog = new MaterialMessageBox(text, caption, buttons)) { // 居中显示 dialog.StartPosition = FormStartPosition.CenterParent; return dialog.ShowDialog(); } } ``` --- #### 三、关键问题解决:lblMessage.Text未声明 1. **设计器验证** - 确保`MaterialMessageBox.Designer.cs`包含: ```csharp private MaterialSkin.Controls.MaterialLabel lblMessage; // ... this.lblMessage = new MaterialSkin.Controls.MaterialLabel(); ``` 2. **代码执行顺序** - 在构造函数中先调用`InitializeComponent()`再操作控件属性: ```csharp public MaterialMessageBox() { InitializeComponent(); // 必须首先执行 lblMessage.Text = "初始化完成"; // 此时控件已存在 } ``` 3. **命名一致性检查** - 在窗体设计器属性面板确认: - 控件名称(Name)必须与代码中使用的名称完全一致 - 类型必须为`MaterialSkin.Controls.MaterialLabel` --- #### 四、使用示例 ```csharp // 在父窗体中调用 DialogResult result = MaterialMessageBox.Show( "确定要删除此文件吗?", "删除确认", MessageBoxButtons.OKCancel ); if (result == DialogResult.OK) { // 执行删除操作 } ``` --- #### 五、样式优化建议 1. **阴影效果** ```csharp this.Elevation = 24; // 设置窗体投影深度 ``` 2. **颜色主题** ```csharp materialSkinManager.ColorScheme = new ColorScheme( Primary.Blue600, Primary.Blue700, Primary.Blue500, Accent.Blue200, TextShade.WHITE ); ``` 3. **动画过渡** ```csharp this.ShowInTaskbar = false; this.Opacity = 0; Timer fadeTimer = new Timer { Interval = 10 }; fadeTimer.Tick += (s, e) => { this.Opacity += 0.1; }; fadeTimer.Start(); ``` --- #### 六、常见问题排查表 | 问题现象 | 解决方案 | |---------|----------| | 控件显示为灰色方块 | 检查是否调用了`MaterialSkinManager.AddFormToManage(this)` | | 文字显示不全 | 设置`lblMessage.AutoSize = false`并指定固定尺寸 | | 按钮点击无响应 | 确认`DialogResult`属性已正确设置 | | 窗体无法拖动 | 添加`MouseDown`事件处理逻辑[^1] | --- ### 相关问题 1. 如何为MaterialSkin对话框添加自定义图标? 2. 如何处理MaterialLabel长文本自动换行? 3. 如何实现MaterialForm的渐入渐出动画效果? 4. MaterialSkin控件如何与Windows原生API交互?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值