利用NativeWindow监视WndProc消息

http://blog.csdn.net/lovefootball/article/details/1784882

在写Windows应用程序的时候,经常会碰到需要修改例如MessageBox或者FileDialog的外观
此时我们需要监视 WndProc的消息
当然也可以直接调用API实现,具体方法请参考
http://www.codeproject.com/csharp/GetSaveFileName.asp?df=100&forumid=96342&exp=0&select=1950454
主要代码如下

[c-sharp:nogutter] view plain copy print ?
  1. using System; 
  2. using System.Runtime.InteropServices; 
  3. using System.Windows.Forms; 
  4. using System.Collections.Generic; 
  5.  
  6. namespace testApplication1 
  7.     public delegate void HookWndProcHandler(ref Message m); 
  8.  
  9.     public class HookWndProc 
  10.     { 
  11.         private Dictionary<Control, NativeWindow> nativeWindows = new Dictionary<Control, NativeWindow>(); 
  12.  
  13.         public event HookWndProcHandler WndProcEvent; 
  14.  
  15.         public void BeginHookProc(Control control) 
  16.         { 
  17.             if(nativeWindows.ContainsKey(control))  
  18.             { 
  19.                 return
  20.             } 
  21.              
  22.             nativeWindows.Add(control, new HookNativeWindow(this, control)); 
  23.         } 
  24.  
  25.         public void EndHookProc(Control control) 
  26.         { 
  27.             if(!nativeWindows.ContainsKey(control))  
  28.             { 
  29.                 return
  30.             } 
  31.  
  32.             NativeWindow window = nativeWindows[control]; 
  33.             nativeWindows.Remove(control); 
  34.             window.ReleaseHandle(); 
  35.             window = null
  36.         } 
  37.  
  38.         protected virtual void WndProc(ref Message m)  
  39.         { 
  40.             FireWndProcEvent(ref m); 
  41.         } 
  42.  
  43.         protected void FireWndProcEvent(ref Message m)  
  44.         { 
  45.             if (WndProcEvent != null
  46.             { 
  47.                 WndProcEvent(ref m); 
  48.             } 
  49.         } 
  50.         #region NativeWindow 
  51.  
  52.         protected class HookNativeWindow : NativeWindow 
  53.         { 
  54.             private HookWndProc hookWndProc; 
  55.  
  56.             public HookNativeWindow(HookWndProc hookWndProc, Control control) 
  57.             { 
  58.                 this.hookWndProc = hookWndProc; 
  59.  
  60.                 if (control.IsHandleCreated) 
  61.                 { 
  62.                     AssignHandle(control.Handle); 
  63.                 } 
  64.                 else 
  65.                 { 
  66.                     control.HandleCreated += new EventHandler(OnControlHandleCreated); 
  67.                 } 
  68.  
  69.                 control.HandleDestroyed += new EventHandler(OnControlHandleDestroyed); 
  70.             } 
  71.  
  72.             private void OnControlHandleCreated(object sender, EventArgs e) 
  73.             { 
  74.                 AssignHandle(((Control)sender).Handle); 
  75.             } 
  76.  
  77.             private void OnControlHandleDestroyed(object sender, EventArgs e) 
  78.             { 
  79.                 ReleaseHandle(); 
  80.             } 
  81.  
  82.             [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] 
  83.             protected override void WndProc(ref Message m) 
  84.             { 
  85.                 hookWndProc.WndProc(ref m); 
  86.                 base.WndProc(ref m); 
  87.             } 
  88.         } 
  89.         #endregion 
  90.     } 
using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Collections.Generic; namespace testApplication1 { public delegate void HookWndProcHandler(ref Message m); public class HookWndProc { private Dictionary<Control, NativeWindow> nativeWindows = new Dictionary<Control, NativeWindow>(); public event HookWndProcHandler WndProcEvent; public void BeginHookProc(Control control) { if(nativeWindows.ContainsKey(control)) { return; } nativeWindows.Add(control, new HookNativeWindow(this, control)); } public void EndHookProc(Control control) { if(!nativeWindows.ContainsKey(control)) { return; } NativeWindow window = nativeWindows[control]; nativeWindows.Remove(control); window.ReleaseHandle(); window = null; } protected virtual void WndProc(ref Message m) { FireWndProcEvent(ref m); } protected void FireWndProcEvent(ref Message m) { if (WndProcEvent != null) { WndProcEvent(ref m); } } #region NativeWindow protected class HookNativeWindow : NativeWindow { private HookWndProc hookWndProc; public HookNativeWindow(HookWndProc hookWndProc, Control control) { this.hookWndProc = hookWndProc; if (control.IsHandleCreated) { AssignHandle(control.Handle); } else { control.HandleCreated += new EventHandler(OnControlHandleCreated); } control.HandleDestroyed += new EventHandler(OnControlHandleDestroyed); } private void OnControlHandleCreated(object sender, EventArgs e) { AssignHandle(((Control)sender).Handle); } private void OnControlHandleDestroyed(object sender, EventArgs e) { ReleaseHandle(); } [System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")] protected override void WndProc(ref Message m) { hookWndProc.WndProc(ref m); base.WndProc(ref m); } } #endregion } }

调用方法,以更改MessageBox的OK按钮文本为例


            HookWndProc hookWndProc
= new HookWndProc();
            hookWndProc.WndProcEvent
+= new HookWndProcHandler(hookWndProc_WndProcEvent);
            hookWndProc.BeginHookProc(
this );
            MessageBox.Show(
" MSG APP " , " MessageBoxCaption " , MessageBoxButtons.OKCancel);
            hookWndProc.EndHookProc(
this );

private void hookWndProc_WndProcEvent( ref Message m)
       
... {
            IntPtr wnd
= FindWindow(null, "MessageBoxCaption");

           
if (wnd != IntPtr.Zero)
           
...{
                SetDlgItemText(wnd,
1, "需要修改的文本");
            }

        }

        [DllImport(
" user32.dll " , EntryPoint = " FindWindow " , CharSet = CharSet.Auto)]
       
private extern static IntPtr FindWindow( string lpClassName, string lpWindowName);

        [DllImport(
" user32.dll " )]
       
public static extern IntPtr SetDlgItemText(IntPtr hwnd, int id, string caption);


也就是说在WndProcEvent事件里面你可以写上你所需要做的事情

如果需要修改FileDialog的外观
则需要在
WndProcEvent事件里面写上如下代码

if (m.Msg == WM_ENTERIDLE)
... {
   
uint dialogHandle = (uint)m.LParam;
   
uint listviewHandle = FindWindowEx(dialogHandle, 0, "SHELLDLL_DefView", "");
   
if (listviewHandle != 0 && listviewHandle != lastListViewHandle)
   
...{
        SendMessage(listviewHandle, WM_COMMAND, (
uint)View, 0);
}

lastListViewHandle
= listviewHandle;



   
/**//// <summary>
   
/// FileListViewType
   
/// </summary>

    public enum FileListView
   
...{
        Icons
= 0x7029,
        SmallIcons
= 0x702a,
        List
= 0x702b,
        Details
= 0x702c,
        Thumbnails
= 0x7031,
        XpThumbnails
= 0x702d
    }



       
/**//// <summary>
       
/// win message : command
       
/// </summary>

        private const uint WM_COMMAND = 0x0111;

       
/**//// <summary>
       
/// win message : enter idle
       
/// </summary>

        private const uint WM_ENTERIDLE = 0x0121;

       
/**//// <summary>
       
/// listview type
       
/// </summary>

        private FileListView view = FileListView.Thumbnails;

       
/**//// <summary>
       
/// dialog handle
       
/// </summary>

        private uint lastListViewHandle = 0;

DllImports
#region DllImports

        [DllImport(
"user32.dll", EntryPoint="SendMessageA", CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
       
private static extern uint SendMessage(uint Hdc, uint Msg_Const, uint wParam, uint lParam);

        [DllImport(
"user32.dll", EntryPoint="FindWindowExA", CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
       
private static extern uint FindWindowEx(uint hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow);

       
#endregion

 SetDlgItemText(wnd, 1, "需要修改的文本");

private const int IDOK = 1;
private const int IDCANCEL = 2;
private const int IDABORT = 3;
private const int IDRETRY = 4;
private const int IDIGNORE = 5;
private const int IDYES = 6;
private const int IDNO = 7;

欢迎转载,请注明出处~~

你可能感兴趣的:(String,object,ListView,command,null,Class)