利用NativeWindow监视WndProc消息

来源:互联网 发布:office 2013 优化版 编辑:程序博客网 时间:2024/06/08 10:39

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 plaincopyprint?
  1. using System; 
  2. using System.Runtime.InteropServices; 
  3. using System.Windows.Forms; 
  4. using System.Collections.Generic; 
  5.  
  6. namespace testApplication1 
  7.     public delegatevoid 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.     } 


调用方法,以更改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);

privatevoid 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 externuint SendMessage(uint Hdc,uint Msg_Const,uint wParam, uint lParam);

        [DllImport(
"user32.dll", EntryPoint="FindWindowExA", CallingConvention=CallingConvention.StdCall,CharSet=CharSet.Ansi)]
       
private static externuint 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;

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

原创粉丝点击