末日这天写篇博客吧,既然没来,那就纪念一下。
这次谈谈自制控件,也就是自定义控件,先上图,再说
1.扩展OpenFileDialog,在OpenFileDialog中添加各种文件(.txt,.jpg,.excel等等)的预览功能
2.重写ListBox,增加折叠、鼠标背影、分类等功能
-----------------------------分割线--------------------------------------------------------------
一、扩展OpenFileDialog
许多软件的打开对话框都有预览功能,最常见的就是图片预览,用鼠标选择一个图片文件后,右侧或者下侧就会有该图片的缩略图(photoshop中属于后者)。在winform编程中,有专门的打开文件对话框的类OpenFileDialog,但是他不提供文件预览功能,封装得实在太好。看看它公开那些接口
提到扩展,很多人可能想到继承它就可以扩展它,可惜OpenFileDialog声明为sealed,不允许从他继承。稍微底层一点的,想到可以通过Win32 API来修改它的显示方式,只可惜,如你所见,它根本没提供Handle属性,更别说HandleCreated、HandleDestroyed等事件了。那么怎么样子搞呢?其实答案还是通过Win32 API,只是我们取得它的句柄的方式要复杂一点而且调用API的时机隐晦了一点。
提示:
1.Win32 API操作窗体需要知道窗体的句柄;
2.不熟悉Win32编程的同学可以先上网查查资料,特别是不知道SetParent、SetWindowPos等API是干嘛的,我觉得以下的看不懂。
为什么说取得它的句柄复杂了一点?难道不是用“FindWindow”、“FindWindowEx”、“ EnumChildWindows”等获取OpenFileDialog的句柄,再用“SetParent”、“SetWindowPos”等API将.net控件(本例中是DataGridView控件,当然可以使其他任何一种)添加到OpenFileDialog中去?没错,以上列举出来的API都是基本要用到的,“只是用在什么地方、什么时候用”是个比较麻烦的问题,原因如下:
1)我们知道OpenfileDialog显示的是模式对话框,也就是说,一旦它ShowDialog(),它以下的代码是不会再执行的,具体原因是什么(我以后的博客会专门讲为什么),你现在可以理解为OpenFileDialog()方法会阻塞调用线程,既然阻塞了调用线程,那么我们再无法控制程序了(直到它返回),根本谈不上再调用API获取OpenFileDialog的句柄然后去操作它。如果有人会说,“我可以另开辟线程去取OpenFileDialog得句柄再操作它”,恩,我不否定这个方法,只是我想说,如果你真的按照这个方法去试,那么肯定会陷入泥潭。因为你不仅要取它的句柄,你还要监视OpenFIleDialog的一举一动,移动、缩放、用户鼠标点击选择文件、更改目录等,然后再操作.net控件(本例中是DataGridView控件,下同),让.net控件去适应OpenFileDialog的大小等等,你会发现你忙死了,甚至有的你根本监视不了,比如用户点击选择文件、更改目录。
2)就算我们能够在OpenFIleDialog显示之后,取得它的句柄,那么什么时候再调用其他API呢?比如什么时候调用SetWindowPos,让.net控件适应OpenFileDialog的大小变化?什么时候知道用户选择文件发生了变化?
所以,API方法什么时候用?用在什么地方?就是接下来要讨论的东西。
我不知道各位在使用各种框架的时候,对“框架”的理解到什么程度,我觉得可以总结成一句话“跟个2b似地注册一些事件,然后苦逼地去写好每一个回调方法,我们却不知道为啥要这样写”,不是么?既然这样,那么我们的API方法只要写在了正确的回调方法中,我们就能到达想要的目的了。考虑几个问题:
1)OpenFileDialog显示,我们向其中添加.net控件。我们什么时候知道它显示?
2)OpenFileDialog大小发生变化时,我们要更新.net控件以适应新的大小。我们什么时候知道OpenFileDialog的大小发生了变化?
3)OpenFileDialog中用户选择的文件发生了变化,我们需要知道新选择的文件路径,用来显示在.net控件中。我们怎么知道选择了什么文件?(这里选择文件指用户用鼠标在OpenFileDialog中单击选取,不是点击“确定”后。)
以上所有的问题,其实在一个地方都可以知道,那就是监听OpenFileDialog窗体的Windows消息,因为一个窗体的任何一个动作都伴随着一系列的Windows消息(这个可以用Spy++查看)。既然这样,那么我们可以在窗体处理Windows消息的回调方法中调用API方法了,也就是窗体的Control.WndProc方法中。之前已经说过了,OpenFileDialog声明为Sealed,提供的接口少之又少,我们几乎根本不可能接触到OpenFileDialog的WndProc,更谈不上监听Windows消息,然后调用API去操作它。这时候,NativeWindow该出场了,先来引用一下MSDN上对NativeWindow的解释:
“提供窗口句柄和窗口过程的低级封装。”
说了像没说一样,其实就是说,将一个窗口句柄与NativeWindow对象绑定后,该NativeWindow对象就能接收到这个窗体的所有消息。说到Windows消息,我想说一下Windows桌面应用程序的运行流程,其实如果看了我前一篇博客的同学应该有些了解,中基本提到了一些。为了配合本次讲解,我再次画了一张图
上图中,虚线框可以看做是一个.net中的Control类对象(或者其派生类,下同,控件即窗体、窗体即控件),正常情况下,Winform程序会按照1->2->3的步骤运行,当我们将Control类对象的Handle(就是我们常说的窗口句柄,做了一下封装)与一个NativeWIndow对象绑定后,程序不再按照1->2->3这样的顺序运行了,他会按照1->2-1->2-2->3这样运行,也就是说,NativeWindow对象可以拦截Control类对象的WIndows消息,我们完全可以在NativeWIndow中重写他的WndProc方法,像处理自己的Windows消息一样去处理Control类对象的消息。所以,我们就可以在NativeWindow对象的WndProc中调用我们的API方法。
接下来,上代码(代码只提供大概思路)
1.扩展对话框
1 public class MultiOpenFileDialog 2 { 3 #region fields 4 private const SetWindowPosFlags UFLAGSHIDE = 5 SetWindowPosFlags.SWP_NOACTIVATE | 6 SetWindowPosFlags.SWP_NOOWNERZORDER | 7 SetWindowPosFlags.SWP_NOMOVE | 8 SetWindowPosFlags.SWP_NOSIZE | 9 SetWindowPosFlags.SWP_HIDEWINDOW;10 #endregion11 public string FileName;12 #region public methods13 public DialogResult ShowDialog()14 {15 return ShowDialog(null);16 }17 public DialogResult ShowDialog(IWin32Window owner)18 {19 using (OpenFileDialog open = new OpenFileDialog())20 {21 MedianForm median = new MedianForm(open);22 median.Show(owner);23 Win32.SetWindowPos(median.Handle, IntPtr.Zero, 0, 0, 0, 0, UFLAGSHIDE); //隐藏中间窗体24 DialogResult dialogresult = open.ShowDialog(median); //将median作为openfileDialog的owner25 median.Close();26 if (dialogresult == DialogResult.OK)27 {28 FileName = open.FileName;29 }30 return dialogresult;31 }32 }33 #endregion34 }
2.监听Dialog的NativeWindow
1 class DialogNativeWindow : NativeWindow,IDisposable 2 { 3 IntPtr handle; //待扩展OpenFileDialog的句柄 4 OpenFileDialog openfiledialog; //待扩展OpenFileDialog 5 DataGridView addControl; //向窗体中添加新的控件 6 ChildControlNativeWindow childNative; 7 bool init = false; 8 9 public DialogNativeWindow(IntPtr handle, OpenFileDialog openfiledialog) 10 { 11 this.handle = handle; 12 this.openfiledialog = openfiledialog; 13 AssignHandle(handle); 14 15 //设置控件信息 16 addControl = new DataGridView(); 17 addControl.Width = 600; 18 addControl.Height = 200; 19 addControl.DataSource = null; 20 } 21 22 #region override methods 23 protected override void WndProc(ref Message m) 24 { 25 switch (m.Msg) 26 { 27 case (int)Msg.WM_SHOWWINDOW: //窗体显示 28 { 29 NativeChild(); 30 AddControl(); 31 break; 32 } 33 case (int)Msg.WM_SIZING: //窗体大小改变 34 { 35 UpdateSize(); 36 break; 37 } 38 case (int)Msg.WM_WINDOWPOSCHANGING: //窗体位置变化 39 { 40 UpdateLocation(m); 41 break; 42 } 43 } 44 base.WndProc(ref m); 45 } 46 #endregion 47 48 #region event handlers 49 void childNative_SelectPathChanged(StringBuilder path) 50 { 51 //处理选择目录变化事件 52 //... 53 } 54 55 void childNative_SelectFileChanged(StringBuilder file) 56 { 57 //处理选择文件变化事件 58 //如果是xls文件,将其显示在datagridview控件中 59 string str = file.ToString(); 60 if (str.ToLower().EndsWith(".xls")) 61 { 62 OledbManager manager = new OledbManager(); 63 if (manager.Connect("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=\'" + str + "\'; Extended Properties='Excel 8.0;'")) 64 { 65 DataTable tb = manager.SearchTable(); 66 if (tb != null) 67 { 68 addControl.Rows.Clear(); 69 addControl.Columns.Clear(); 70 foreach (DataColumn col in tb.Columns) 71 { 72 addControl.Columns.Add(col.ColumnName, col.Caption); 73 } 74 foreach (DataRow row in tb.Rows) 75 { 76 object[] objs = new object[tb.Columns.Count]; 77 for (int i = 0; i < tb.Columns.Count; ++i) 78 { 79 objs[i] = row[i]; 80 } 81 addControl.Rows.Add(objs); 82 } 83 } 84 } 85 } 86 else 87 { 88 addControl.Rows.Clear(); 89 addControl.Columns.Clear(); 90 } 91 } 92 #endregion 93 94 #region private methods 95 private void NativeChild() 96 { 97 //查找openfileDialog中的子控件 98 Win32.EnumChildWindows(handle, new Win32.EnumWindowsCallBack(WindowCallBack), 0); 99 }100 private void AddControl()101 {102 //添加控件到OpenFileDialog界面103 Win32.SetParent(addControl.Handle, handle);104 RECT currentSize = new RECT();105 Win32.GetClientRect(handle, ref currentSize);106 addControl.Height = (int)currentSize.Height;107 addControl.Location = new Point((int)(currentSize.Width - addControl.Width), 0);108 109 init = true;110 }111 private void UpdateLocation(Message m)112 {113 if (!init) //只初始化openfileDialog的大小一次114 {115 WINDOWPOS pos = (WINDOWPOS)Marshal.PtrToStructure(m.LParam, typeof(WINDOWPOS));116 if (pos.flags != 0 && ((pos.flags & (int)SWP_Flags.SWP_NOSIZE) != (int)SWP_Flags.SWP_NOSIZE))117 {118 pos.cx += addControl.Width; //修改OpenfileDialog的宽度119 Marshal.StructureToPtr(pos, m.LParam, true);120 121 RECT currentSize = new RECT();122 Win32.GetClientRect(handle, ref currentSize);123 addControl.Height = (int)currentSize.Height;124 }125 }126 }127 private void UpdateSize()128 {129 RECT currentSize = new RECT();130 Win32.GetClientRect(handle, ref currentSize); 131 Win32.SetWindowPos(addControl.Handle, (IntPtr)ZOrderPos.HWND_BOTTOM, 0, 0, (int)addControl.Width, (int)currentSize.Height, UFLAGSSIZEEX); //新添加的控件与openfileDialog大小一致132 }133 private bool WindowCallBack(IntPtr handle, int lparam)134 {135 StringBuilder wndClass = new StringBuilder(256);136 Win32.GetClassName(handle, wndClass, wndClass.Capacity);//获取控件类名137 138 if (wndClass.ToString().StartsWith("#32770")) //找到目标控件139 {140 childNative = new ChildControlNativeWindow(handle);141 childNative.SelectFileChanged += new ChildControlNativeWindow.SelectFileChangedEventHandler(childNative_SelectFileChanged);142 childNative.SelectPathChanged += new ChildControlNativeWindow.SelectPathChangedEventHandler(childNative_SelectPathChanged);143 return true;144 }145 return true;146 }147 #endregion148 149 #region enums150 private const SetWindowPosFlags UFLAGSSIZEEX =151 SetWindowPosFlags.SWP_NOACTIVATE |152 SetWindowPosFlags.SWP_NOOWNERZORDER |153 SetWindowPosFlags.SWP_NOMOVE |154 SetWindowPosFlags.SWP_ASYNCWINDOWPOS |155 SetWindowPosFlags.SWP_DEFERERASE;156 private const SetWindowPosFlags UFLAGSSIZE =157 SetWindowPosFlags.SWP_NOACTIVATE |158 SetWindowPosFlags.SWP_NOOWNERZORDER |159 SetWindowPosFlags.SWP_NOMOVE;160 private const SetWindowPosFlags UFLAGSHIDE =161 SetWindowPosFlags.SWP_NOACTIVATE |162 SetWindowPosFlags.SWP_NOOWNERZORDER |163 SetWindowPosFlags.SWP_NOMOVE |164 SetWindowPosFlags.SWP_NOSIZE |165 SetWindowPosFlags.SWP_HIDEWINDOW;166 #endregion167 168 #region IDisposable 成员169 170 public void Dispose()171 {172 ReleaseHandle(); //释放与openfileDialog的句柄关联173 if (childNative != null)174 {175 childNative.SelectFileChanged -= new ChildControlNativeWindow.SelectFileChangedEventHandler(childNative_SelectFileChanged);176 childNative.SelectPathChanged -= new ChildControlNativeWindow.SelectPathChangedEventHandler(childNative_SelectPathChanged);177 childNative.Dispose(); 178 }179 180 }181 182 #endregion183 }
3.监听子控件的NativeWindow
1 class ChildControlNativeWindow : NativeWindow,IDisposable 2 { 3 IntPtr handle; //需要被监听消息的子控件句柄 4 public ChildControlNativeWindow(IntPtr handle) 5 { 6 this.handle = handle; 7 AssignHandle(handle); 8 } 9 10 #region override methods11 protected override void WndProc(ref Message m)12 {13 switch (m.Msg)14 {15 case (int)Msg.WM_NOTIFY:16 OFNOTIFY ofNotify = (OFNOTIFY)Marshal.PtrToStructure(m.LParam, typeof(OFNOTIFY));17 if (ofNotify.hdr.code == (uint)DialogChangeStatus.CDN_SELCHANGE) //openfileDialog选择文件发生变化18 {19 StringBuilder file = new StringBuilder(256);20 Win32.SendMessage(Win32.GetParent(handle), (int)DialogChangeProperties.CDM_GETFILEPATH, (int)256, file);21 if (SelectFileChanged != null)22 SelectFileChanged(file); //通知注册者23 }24 else if (ofNotify.hdr.code == (uint)DialogChangeStatus.CDN_FOLDERCHANGE) //openfileDialog选择目录发生变化25 {26 StringBuilder path = new StringBuilder(256);27 Win32.SendMessage(Win32.GetParent(handle), (int)DialogChangeProperties.CDM_GETFOLDERPATH, (int)256, path);28 if (SelectPathChanged != null)29 SelectPathChanged(path); //通知注册者30 }31 break;32 }33 base.WndProc(ref m);34 }35 #endregion36 37 #region delegate38 public delegate void SelectFileChangedEventHandler(StringBuilder file); 39 public delegate void SelectPathChangedEventHandler(StringBuilder path);40 #endregion41 42 #region events43 public event SelectFileChangedEventHandler SelectFileChanged; //当openfileDialog的选择文件发生变化时发生44 public event SelectPathChangedEventHandler SelectPathChanged; //当openfileDialog的选择目录发生变化时发生45 #endregion46 47 #region IDisposable 成员48 49 public void Dispose()50 {51 ReleaseHandle(); //终止与子控件句柄的关联52 }53 54 #endregion55 }
4.中间过渡窗体,用来获取OpenFileDialog的句柄
1 class MedianForm : Form 2 { 3 OpenFileDialog open = null; 4 DialogNativeWindow dialognative; 5 6 public MedianForm(OpenFileDialog open) 7 { 8 this.open = open; 9 StartPosition = FormStartPosition.Manual;10 Location = new System.Drawing.Point(-1000, -1000); //避免界面闪烁11 }12 protected override void OnClosing(System.ComponentModel.CancelEventArgs e)13 {14 if (dialognative != null)15 {16 dialognative.Dispose(); //释放资源17 }18 base.OnClosing(e);19 }20 protected override void WndProc(ref Message m)21 {22 if (m.Msg == (int) Msg.WM_ACTIVATE)23 {24 dialognative = new DialogNativeWindow(m.LParam, open); //m.LParam为要打开的窗口句柄,开始监听OpenFileDialog的Windows消息25 }26 base.WndProc(ref m);27 }28 }
5.访问Excel文件的类
1 class OledbManager 2 { 3 OleDbConnection conn; 4 ///5 /// 连接excel文件 6 /// 7 /// 8 ///9 public bool Connect(string connstr)10 {11 try12 {13 conn = new OleDbConnection(connstr);14 conn.Open();15 return true;16 }17 catch18 {19 return false;20 }21 }22 /// 23 /// 查找第一张表中的数据24 /// 25 ///26 public DataTable SearchTable()27 {28 try29 {30 DataTable tb = new DataTable();31 string sql = "select * from [Sheet1$]";32 OleDbCommand com = new OleDbCommand(sql, conn);33 OleDbDataAdapter adp = new OleDbDataAdapter(com);34 adp.Fill(tb);35 return tb;36 }37 catch38 {39 return null;40 }41 }42 }
6.几个Win32结构体、枚举类型以及API声明(本代码参考CodeProject上的一篇文章)
1 public static class Win32 2 { 3 #region Delegates 4 public delegate bool EnumWindowsCallBack(IntPtr hWnd, int lParam); 5 #endregion 6 7 #region USER32 8 [DllImport("user32.dll", CharSet = CharSet.Auto)] 9 public static extern IntPtr GetParent(IntPtr hWnd); 10 [DllImport("User32.Dll")] 11 public static extern int GetDlgCtrlID(IntPtr hWndCtl); 12 [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] 13 public static extern int MapWindowPoints(IntPtr hWnd, IntPtr hWndTo, ref POINT pt, int cPoints); 14 [DllImport("user32.dll", SetLastError = true)] 15 public static extern bool GetWindowInfo(IntPtr hwnd, out WINDOWINFO pwi); 16 [DllImport("User32.Dll")] 17 public static extern void GetWindowText(IntPtr hWnd, StringBuilder param, int length); 18 [DllImport("User32.Dll")] 19 public static extern void GetClassName(IntPtr hWnd, StringBuilder param, int length); 20 [DllImport("user32.Dll")] 21 public static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsCallBack lpEnumFunc, int lParam); 22 [DllImport("user32.Dll")] 23 public static extern bool EnumWindows(EnumWindowsCallBack lpEnumFunc, int lParam); 24 [DllImport("User32.dll", CharSet = CharSet.Auto)] 25 public static extern bool ReleaseCapture(); 26 [DllImport("user32.dll", CharSet = CharSet.Auto)] 27 public static extern IntPtr SetCapture(IntPtr hWnd); 28 [DllImport("user32.dll", CharSet = CharSet.Auto)] 29 public static extern IntPtr ChildWindowFromPointEx(IntPtr hParent, POINT pt, ChildFromPointFlags flags); 30 [DllImport("user32.dll", EntryPoint = "FindWindowExA", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 31 public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); 32 [DllImport("user32.dll")] 33 public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); 34 [DllImport("user32.dll", CharSet = CharSet.Auto)] 35 public static extern int PostMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); 36 [DllImport("user32.dll", CharSet = CharSet.Auto)] 37 public static extern int PostMessage(IntPtr hWnd, int msg, int wParam, int lParam); 38 [DllImport("user32.dll", CharSet = CharSet.Auto)] 39 public static extern int SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam); 40 [DllImport("user32.dll", CharSet = CharSet.Auto)] 41 public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam); 42 [DllImport("user32.dll", CharSet = CharSet.Auto)] 43 public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder param); 44 [DllImport("user32.dll", CharSet = CharSet.Auto)] 45 public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, char[] chars); 46 [DllImport("user32.dll", CharSet = CharSet.Auto)] 47 public static extern IntPtr BeginDeferWindowPos(int nNumWindows); 48 [DllImport("user32.dll", CharSet = CharSet.Auto)] 49 public static extern IntPtr DeferWindowPos(IntPtr hWinPosInfo, IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags); 50 [DllImport("user32.dll", CharSet = CharSet.Auto)] 51 public static extern bool EndDeferWindowPos(IntPtr hWinPosInfo); 52 [DllImport("user32.dll", CharSet = CharSet.Auto)] 53 public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int Width, int Height, SetWindowPosFlags flags); 54 [DllImport("user32.dll")] 55 public static extern bool GetWindowRect(IntPtr hwnd, ref RECT rect); 56 [DllImport("user32.dll")] 57 public static extern bool GetClientRect(IntPtr hwnd, ref RECT rect); 58 #endregion 59 } 60 61 #region SWP_Flags 62 [Flags] 63 public enum SWP_Flags 64 { 65 SWP_NOSIZE = 0x0001, 66 SWP_NOMOVE = 0x0002, 67 SWP_NOZORDER = 0x0004, 68 SWP_NOACTIVATE = 0x0010, 69 SWP_FRAMECHANGED = 0x0020, /* The frame changed: send WM_NCCALCSIZE */ 70 SWP_SHOWWINDOW = 0x0040, 71 SWP_HIDEWINDOW = 0x0080, 72 SWP_NOOWNERZORDER = 0x0200, /* Don't do owner Z ordering */ 73 74 SWP_DRAWFRAME = SWP_FRAMECHANGED, 75 SWP_NOREPOSITION = SWP_NOOWNERZORDER 76 } 77 #endregion 78 79 #region DialogChangeStatus 80 public enum DialogChangeStatus : long 81 { 82 CDN_FIRST = 0xFFFFFDA7, 83 CDN_INITDONE = (CDN_FIRST - 0x0000), 84 CDN_SELCHANGE = (CDN_FIRST - 0x0001), 85 CDN_FOLDERCHANGE = (CDN_FIRST - 0x0002), 86 CDN_SHAREVIOLATION = (CDN_FIRST - 0x0003), 87 CDN_HELP = (CDN_FIRST - 0x0004), 88 CDN_FILEOK = (CDN_FIRST - 0x0005), 89 CDN_TYPECHANGE = (CDN_FIRST - 0x0006), 90 } 91 #endregion 92 93 #region DialogChangeProperties 94 public enum DialogChangeProperties 95 { 96 CDM_FIRST = (0x400 + 100), 97 CDM_GETSPEC = (CDM_FIRST + 0x0000), 98 CDM_GETFILEPATH = (CDM_FIRST + 0x0001), 99 CDM_GETFOLDERPATH = (CDM_FIRST + 0x0002),100 CDM_GETFOLDERIDLIST = (CDM_FIRST + 0x0003),101 CDM_SETCONTROLTEXT = (CDM_FIRST + 0x0004),102 CDM_HIDECONTROL = (CDM_FIRST + 0x0005),103 CDM_SETDEFEXT = (CDM_FIRST + 0x0006)104 }105 #endregion106 107 #region ImeNotify108 public enum ImeNotify109 {110 IMN_CLOSESTATUSWINDOW = 0x0001,111 IMN_OPENSTATUSWINDOW = 0x0002,112 IMN_CHANGECANDIDATE = 0x0003,113 IMN_CLOSECANDIDATE = 0x0004,114 IMN_OPENCANDIDATE = 0x0005,115 IMN_SETCONVERSIONMODE = 0x0006,116 IMN_SETSENTENCEMODE = 0x0007,117 IMN_SETOPENSTATUS = 0x0008,118 IMN_SETCANDIDATEPOS = 0x0009,119 IMN_SETCOMPOSITIONFONT = 0x000A,120 IMN_SETCOMPOSITIONWINDOW = 0x000B,121 IMN_SETSTATUSWINDOWPOS = 0x000C,122 IMN_GUIDELINE = 0x000D,123 IMN_PRIVATE = 0x000E124 }125 #endregion126 127 #region FolderViewMode128 public enum FolderViewMode129 {130 Default = 0x7028,131 Icon = Default + 1,132 SmallIcon = Default + 2,133 List = Default + 3,134 Details = Default + 4,135 Thumbnails = Default + 5,136 Title = Default + 6,137 Thumbstrip = Default + 7,138 }139 #endregion140 141 #region Enum DialogViewProperty142 public enum DefaultViewType143 {144 Icons = 0x7029,145 List = 0x702b,146 Details = 0x702c,147 Thumbnails = 0x702d,148 Tiles = 0x702e,149 }150 #endregion151 152 #region ButtonStyle153 public enum ButtonStyle : long154 {155 BS_PUSHBUTTON = 0x00000000,156 BS_DEFPUSHBUTTON = 0x00000001,157 BS_CHECKBOX = 0x00000002,158 BS_AUTOCHECKBOX = 0x00000003,159 BS_RADIOBUTTON = 0x00000004,160 BS_3STATE = 0x00000005,161 BS_AUTO3STATE = 0x00000006,162 BS_GROUPBOX = 0x00000007,163 BS_USERBUTTON = 0x00000008,164 BS_AUTORADIOBUTTON = 0x00000009,165 BS_PUSHBOX = 0x0000000A,166 BS_OWNERDRAW = 0x0000000B,167 BS_TYPEMASK = 0x0000000F,168 BS_LEFTTEXT = 0x00000020,169 BS_TEXT = 0x00000000,170 BS_ICON = 0x00000040,171 BS_BITMAP = 0x00000080,172 BS_LEFT = 0x00000100,173 BS_RIGHT = 0x00000200,174 BS_CENTER = 0x00000300,175 BS_TOP = 0x00000400,176 BS_BOTTOM = 0x00000800,177 BS_VCENTER = 0x00000C00,178 BS_PUSHLIKE = 0x00001000,179 BS_MULTILINE = 0x00002000,180 BS_NOTIFY = 0x00004000,181 BS_FLAT = 0x00008000,182 BS_RIGHTBUTTON = BS_LEFTTEXT183 }184 #endregion185 186 #region ZOrderPos187 public enum ZOrderPos188 {189 HWND_TOP = 0,190 HWND_BOTTOM = 1,191 HWND_TOPMOST = -1,192 HWND_NOTOPMOST = -2193 }194 #endregion195 196 #region Static Control Styles197 public enum StaticControlStyles : long198 {199 SS_LEFT = 0x00000000,200 SS_CENTER = 0x00000001,201 SS_RIGHT = 0x00000002,202 SS_ICON = 0x00000003,203 SS_BLACKRECT = 0x00000004,204 SS_GRAYRECT = 0x00000005,205 SS_WHITERECT = 0x00000006,206 SS_BLACKFRAME = 0x00000007,207 SS_GRAYFRAME = 0x00000008,208 SS_WHITEFRAME = 0x00000009,209 SS_USERITEM = 0x0000000A,210 SS_SIMPLE = 0x0000000B,211 SS_LEFTNOWORDWRAP = 0x0000000C,212 SS_OWNERDRAW = 0x0000000D,213 SS_BITMAP = 0x0000000E,214 SS_ENHMETAFILE = 0x0000000F,215 SS_ETCHEDHORZ = 0x00000010,216 SS_ETCHEDVERT = 0x00000011,217 SS_ETCHEDFRAME = 0x00000012,218 SS_TYPEMASK = 0x0000001F,219 SS_REALSIZECONTROL = 0x00000040,220 SS_NOPREFIX = 0x00000080, /* Don't do "&" character translation */221 SS_NOTIFY = 0x00000100,222 SS_CENTERIMAGE = 0x00000200,223 SS_RIGHTJUST = 0x00000400,224 SS_REALSIZEIMAGE = 0x00000800,225 SS_SUNKEN = 0x00001000,226 SS_EDITCONTROL = 0x00002000,227 SS_ENDELLIPSIS = 0x00004000,228 SS_PATHELLIPSIS = 0x00008000,229 SS_WORDELLIPSIS = 0x0000C000,230 SS_ELLIPSISMASK = 0x0000C000231 }232 #endregion233 234 #region Combo Box styles235 public enum ComboBoxStyles : long236 {237 CBS_SIMPLE = 0x0001,238 CBS_DROPDOWN = 0x0002,239 CBS_DROPDOWNLIST = 0x0003,240 CBS_OWNERDRAWFIXED = 0x0010,241 CBS_OWNERDRAWVARIABLE = 0x0020,242 CBS_AUTOHSCROLL = 0x0040,243 CBS_OEMCONVERT = 0x0080,244 CBS_SORT = 0x0100,245 CBS_HASSTRINGS = 0x0200,246 CBS_NOINTEGRALHEIGHT = 0x0400,247 CBS_DISABLENOSCROLL = 0x0800,248 CBS_UPPERCASE = 0x2000,249 CBS_LOWERCASE = 0x4000250 }251 #endregion252 253 #region Window Styles254 public enum WindowStyles : long255 {256 WS_OVERLAPPED = 0x00000000,257 WS_POPUP = 0x80000000,258 WS_CHILD = 0x40000000,259 WS_MINIMIZE = 0x20000000,260 WS_VISIBLE = 0x10000000,261 WS_DISABLED = 0x08000000,262 WS_CLIPSIBLINGS = 0x04000000,263 WS_CLIPCHILDREN = 0x02000000,264 WS_MAXIMIZE = 0x01000000,265 WS_CAPTION = 0x00C00000,266 WS_BORDER = 0x00800000,267 WS_DLGFRAME = 0x00400000,268 WS_VSCROLL = 0x00200000,269 WS_HSCROLL = 0x00100000,270 WS_SYSMENU = 0x00080000,271 WS_THICKFRAME = 0x00040000,272 WS_GROUP = 0x00020000,273 WS_TABSTOP = 0x00010000,274 WS_MINIMIZEBOX = 0x00020000,275 WS_MAXIMIZEBOX = 0x00010000,276 WS_TILED = 0x00000000,277 WS_ICONIC = 0x20000000,278 WS_SIZEBOX = 0x00040000,279 WS_POPUPWINDOW = 0x80880000,280 WS_OVERLAPPEDWINDOW = 0x00CF0000,281 WS_TILEDWINDOW = 0x00CF0000,282 WS_CHILDWINDOW = 0x40000000283 }284 #endregion285 286 #region Window Extended Styles287 public enum WindowExStyles288 {289 WS_EX_DLGMODALFRAME = 0x00000001,290 WS_EX_NOPARENTNOTIFY = 0x00000004,291 WS_EX_TOPMOST = 0x00000008,292 WS_EX_ACCEPTFILES = 0x00000010,293 WS_EX_TRANSPARENT = 0x00000020,294 WS_EX_MDICHILD = 0x00000040,295 WS_EX_TOOLWINDOW = 0x00000080,296 WS_EX_WINDOWEDGE = 0x00000100,297 WS_EX_CLIENTEDGE = 0x00000200,298 WS_EX_CONTEXTHELP = 0x00000400,299 WS_EX_RIGHT = 0x00001000,300 WS_EX_LEFT = 0x00000000,301 WS_EX_RTLREADING = 0x00002000,302 WS_EX_LTRREADING = 0x00000000,303 WS_EX_LEFTSCROLLBAR = 0x00004000,304 WS_EX_RIGHTSCROLLBAR = 0x00000000,305 WS_EX_CONTROLPARENT = 0x00010000,306 WS_EX_STATICEDGE = 0x00020000,307 WS_EX_APPWINDOW = 0x00040000,308 WS_EX_OVERLAPPEDWINDOW = 0x00000300,309 WS_EX_PALETTEWINDOW = 0x00000188,310 WS_EX_LAYERED = 0x00080000311 }312 #endregion313 314 #region ChildFromPointFlags315 public enum ChildFromPointFlags316 {317 CWP_ALL = 0x0000,318 CWP_SKIPINVISIBLE = 0x0001,319 CWP_SKIPDISABLED = 0x0002,320 CWP_SKIPTRANSPARENT = 0x0004321 }322 #endregion323 324 #region HitTest325 public enum HitTest326 {327 HTERROR = (-2),328 HTTRANSPARENT = (-1),329 HTNOWHERE = 0,330 HTCLIENT = 1,331 HTCAPTION = 2,332 HTSYSMENU = 3,333 HTGROWBOX = 4,334 HTSIZE = HTGROWBOX,335 HTMENU = 5,336 HTHSCROLL = 6,337 HTVSCROLL = 7,338 HTMINBUTTON = 8,339 HTMAXBUTTON = 9,340 HTLEFT = 10,341 HTRIGHT = 11,342 HTTOP = 12,343 HTTOPLEFT = 13,344 HTTOPRIGHT = 14,345 HTBOTTOM = 15,346 HTBOTTOMLEFT = 16,347 HTBOTTOMRIGHT = 17,348 HTBORDER = 18,349 HTREDUCE = HTMINBUTTON,350 HTZOOM = HTMAXBUTTON,351 HTSIZEFIRST = HTLEFT,352 HTSIZELAST = HTBOTTOMRIGHT,353 HTOBJECT = 19,354 HTCLOSE = 20,355 HTHELP = 21356 }357 #endregion358 359 #region Windows Messages360 public enum Msg361 {362 WM_NULL = 0x0000,363 WM_CREATE = 0x0001,364 WM_DESTROY = 0x0002,365 WM_MOVE = 0x0003,366 WM_SIZE = 0x0005,367 WM_ACTIVATE = 0x0006,368 WM_SETFOCUS = 0x0007,369 WM_KILLFOCUS = 0x0008,370 WM_ENABLE = 0x000A,371 WM_SETREDRAW = 0x000B,372 WM_SETTEXT = 0x000C,373 WM_GETTEXT = 0x000D,374 WM_GETTEXTLENGTH = 0x000E,375 WM_PAINT = 0x000F,376 WM_CLOSE = 0x0010,377 WM_QUERYENDSESSION = 0x0011,378 WM_QUIT = 0x0012,379 WM_QUERYOPEN = 0x0013,380 WM_ERASEBKGND = 0x0014,381 WM_SYSCOLORCHANGE = 0x0015,382 WM_ENDSESSION = 0x0016,383 WM_SHOWWINDOW = 0x0018,384 WM_CTLCOLOR = 0x0019,385 WM_WININICHANGE = 0x001A,386 WM_SETTINGCHANGE = 0x001A,387 WM_DEVMODECHANGE = 0x001B,388 WM_ACTIVATEAPP = 0x001C,389 WM_FONTCHANGE = 0x001D,390 WM_TIMECHANGE = 0x001E,391 WM_CANCELMODE = 0x001F,392 WM_SETCURSOR = 0x0020,393 WM_MOUSEACTIVATE = 0x0021,394 WM_CHILDACTIVATE = 0x0022,395 WM_QUEUESYNC = 0x0023,396 WM_GETMINMAXINFO = 0x0024,397 WM_PAINTICON = 0x0026,398 WM_ICONERASEBKGND = 0x0027,399 WM_NEXTDLGCTL = 0x0028,400 WM_SPOOLERSTATUS = 0x002A,401 WM_DRAWITEM = 0x002B,402 WM_MEASUREITEM = 0x002C,403 WM_DELETEITEM = 0x002D,404 WM_VKEYTOITEM = 0x002E,405 WM_CHARTOITEM = 0x002F,406 WM_SETFONT = 0x0030,407 WM_GETFONT = 0x0031,408 WM_SETHOTKEY = 0x0032,409 WM_GETHOTKEY = 0x0033,410 WM_QUERYDRAGICON = 0x0037,411 WM_COMPAREITEM = 0x0039,412 WM_GETOBJECT = 0x003D,413 WM_COMPACTING = 0x0041,414 WM_COMMNOTIFY = 0x0044,415 WM_WINDOWPOSCHANGING = 0x0046,416 WM_WINDOWPOSCHANGED = 0x0047,417 WM_POWER = 0x0048,418 WM_COPYDATA = 0x004A,419 WM_CANCELJOURNAL = 0x004B,420 WM_NOTIFY = 0x004E,421 WM_INPUTLANGCHANGEREQUEST = 0x0050,422 WM_INPUTLANGCHANGE = 0x0051,423 WM_TCARD = 0x0052,424 WM_HELP = 0x0053,425 WM_USERCHANGED = 0x0054,426 WM_NOTIFYFORMAT = 0x0055,427 WM_CONTEXTMENU = 0x007B,428 WM_STYLECHANGING = 0x007C,429 WM_STYLECHANGED = 0x007D,430 WM_DISPLAYCHANGE = 0x007E,431 WM_GETICON = 0x007F,432 WM_SETICON = 0x0080,433 WM_NCCREATE = 0x0081,434 WM_NCDESTROY = 0x0082,435 WM_NCCALCSIZE = 0x0083,436 WM_NCHITTEST = 0x0084,437 WM_NCPAINT = 0x0085,438 WM_NCACTIVATE = 0x0086,439 WM_GETDLGCODE = 0x0087,440 WM_SYNCPAINT = 0x0088,441 WM_NCMOUSEMOVE = 0x00A0,442 WM_NCLBUTTONDOWN = 0x00A1,443 WM_NCLBUTTONUP = 0x00A2,444 WM_NCLBUTTONDBLCLK = 0x00A3,445 WM_NCRBUTTONDOWN = 0x00A4,446 WM_NCRBUTTONUP = 0x00A5,447 WM_NCRBUTTONDBLCLK = 0x00A6,448 WM_NCMBUTTONDOWN = 0x00A7,449 WM_NCMBUTTONUP = 0x00A8,450 WM_NCMBUTTONDBLCLK = 0x00A9,451 WM_NCXBUTTONDOWN = 0x00AB,452 WM_NCXBUTTONUP = 0x00AC,453 WM_NCXBUTTONDBLCLK = 0x00AD,454 WM_KEYDOWN = 0x0100,455 WM_KEYUP = 0x0101,456 WM_CHAR = 0x0102,457 WM_DEADCHAR = 0x0103,458 WM_SYSKEYDOWN = 0x0104,459 WM_SYSKEYUP = 0x0105,460 WM_SYSCHAR = 0x0106,461 WM_SYSDEADCHAR = 0x0107,462 WM_KEYLAST = 0x0108,463 WM_IME_STARTCOMPOSITION = 0x010D,464 WM_IME_ENDCOMPOSITION = 0x010E,465 WM_IME_COMPOSITION = 0x010F,466 WM_IME_KEYLAST = 0x010F,467 WM_INITDIALOG = 0x0110,468 WM_COMMAND = 0x0111,469 WM_SYSCOMMAND = 0x0112,470 WM_TIMER = 0x0113,471 WM_HSCROLL = 0x0114,472 WM_VSCROLL = 0x0115,473 WM_INITMENU = 0x0116,474 WM_INITMENUPOPUP = 0x0117,475 WM_MENUSELECT = 0x011F,476 WM_MENUCHAR = 0x0120,477 WM_ENTERIDLE = 0x0121,478 WM_MENURBUTTONUP = 0x0122,479 WM_MENUDRAG = 0x0123,480 WM_MENUGETOBJECT = 0x0124,481 WM_UNINITMENUPOPUP = 0x0125,482 WM_MENUCOMMAND = 0x0126,483 WM_CTLCOLORMSGBOX = 0x0132,484 WM_CTLCOLOREDIT = 0x0133,485 WM_CTLCOLORLISTBOX = 0x0134,486 WM_CTLCOLORBTN = 0x0135,487 WM_CTLCOLORDLG = 0x0136,488 WM_CTLCOLORSCROLLBAR = 0x0137,489 WM_CTLCOLORSTATIC = 0x0138,490 WM_MOUSEMOVE = 0x0200,491 WM_LBUTTONDOWN = 0x0201,492 WM_LBUTTONUP = 0x0202,493 WM_LBUTTONDBLCLK = 0x0203,494 WM_RBUTTONDOWN = 0x0204,495 WM_RBUTTONUP = 0x0205,496 WM_RBUTTONDBLCLK = 0x0206,497 WM_MBUTTONDOWN = 0x0207,498 WM_MBUTTONUP = 0x0208,499 WM_MBUTTONDBLCLK = 0x0209,500 WM_MOUSEWHEEL = 0x020A,501 WM_XBUTTONDOWN = 0x020B,502 WM_XBUTTONUP = 0x020C,503 WM_XBUTTONDBLCLK = 0x020D,504 WM_PARENTNOTIFY = 0x0210,505 WM_ENTERMENULOOP = 0x0211,506 WM_EXITMENULOOP = 0x0212,507 WM_NEXTMENU = 0x0213,508 WM_SIZING = 0x0214,509 WM_CAPTURECHANGED = 0x0215,510 WM_MOVING = 0x0216,511 WM_DEVICECHANGE = 0x0219,512 WM_MDICREATE = 0x0220,513 WM_MDIDESTROY = 0x0221,514 WM_MDIACTIVATE = 0x0222,515 WM_MDIRESTORE = 0x0223,516 WM_MDINEXT = 0x0224,517 WM_MDIMAXIMIZE = 0x0225,518 WM_MDITILE = 0x0226,519 WM_MDICASCADE = 0x0227,520 WM_MDIICONARRANGE = 0x0228,521 WM_MDIGETACTIVE = 0x0229,522 WM_MDISETMENU = 0x0230,523 WM_ENTERSIZEMOVE = 0x0231,524 WM_EXITSIZEMOVE = 0x0232,525 WM_DROPFILES = 0x0233,526 WM_MDIREFRESHMENU = 0x0234,527 WM_IME_SETCONTEXT = 0x0281,528 WM_IME_NOTIFY = 0x0282,529 WM_IME_CONTROL = 0x0283,530 WM_IME_COMPOSITIONFULL = 0x0284,531 WM_IME_SELECT = 0x0285,532 WM_IME_CHAR = 0x0286,533 WM_IME_REQUEST = 0x0288,534 WM_IME_KEYDOWN = 0x0290,535 WM_IME_KEYUP = 0x0291,536 WM_MOUSEHOVER = 0x02A1,537 WM_MOUSELEAVE = 0x02A3,538 WM_CUT = 0x0300,539 WM_COPY = 0x0301,540 WM_PASTE = 0x0302,541 WM_CLEAR = 0x0303,542 WM_UNDO = 0x0304,543 WM_RENDERFORMAT = 0x0305,544 WM_RENDERALLFORMATS = 0x0306,545 WM_DESTROYCLIPBOARD = 0x0307,546 WM_DRAWCLIPBOARD = 0x0308,547 WM_PAINTCLIPBOARD = 0x0309,548 WM_VSCROLLCLIPBOARD = 0x030A,549 WM_SIZECLIPBOARD = 0x030B,550 WM_ASKCBFORMATNAME = 0x030C,551 WM_CHANGECBCHAIN = 0x030D,552 WM_HSCROLLCLIPBOARD = 0x030E,553 WM_QUERYNEWPALETTE = 0x030F,554 WM_PALETTEISCHANGING = 0x0310,555 WM_PALETTECHANGED = 0x0311,556 WM_HOTKEY = 0x0312,557 WM_PRINT = 0x0317,558 WM_PRINTCLIENT = 0x0318,559 WM_THEME_CHANGED = 0x031A,560 WM_HANDHELDFIRST = 0x0358,561 WM_HANDHELDLAST = 0x035F,562 WM_AFXFIRST = 0x0360,563 WM_AFXLAST = 0x037F,564 WM_PENWINFIRST = 0x0380,565 WM_PENWINLAST = 0x038F,566 WM_APP = 0x8000,567 WM_USER = 0x0400,568 WM_REFLECT = WM_USER + 0x1c00569 }570 #endregion571 572 #region SetWindowPosFlags573 public enum SetWindowPosFlags574 {575 SWP_NOSIZE = 0x0001,576 SWP_NOMOVE = 0x0002,577 SWP_NOZORDER = 0x0004,578 SWP_NOREDRAW = 0x0008,579 SWP_NOACTIVATE = 0x0010,580 SWP_FRAMECHANGED = 0x0020,581 SWP_SHOWWINDOW = 0x0040,582 SWP_HIDEWINDOW = 0x0080,583 SWP_NOCOPYBITS = 0x0100,584 SWP_NOOWNERZORDER = 0x0200,585 SWP_NOSENDCHANGING = 0x0400,586 SWP_DRAWFRAME = 0x0020,587 SWP_NOREPOSITION = 0x0200,588 SWP_DEFERERASE = 0x2000,589 SWP_ASYNCWINDOWPOS = 0x4000590 }591 #endregion592 }593 594 #region WINDOWINFO595 [StructLayout(LayoutKind.Sequential)]596 public struct WINDOWINFO597 {598 public UInt32 cbSize;599 public RECT rcWindow;600 public RECT rcClient;601 public UInt32 dwStyle;602 public UInt32 dwExStyle;603 public UInt32 dwWindowStatus;604 public UInt32 cxWindowBorders;605 public UInt32 cyWindowBorders;606 public UInt16 atomWindowType;607 public UInt16 wCreatorVersion;608 }609 #endregion610 611 #region POINT612 [StructLayout(LayoutKind.Sequential)]613 public struct POINT614 {615 public int x;616 public int y;617 618 #region Constructors619 public POINT(int x, int y)620 {621 this.x = x;622 this.y = y;623 }624 625 public POINT(Point point)626 {627 x = point.X;628 y = point.Y;629 }630 #endregion631 }632 #endregion633 634 #region RECT635 [StructLayout(LayoutKind.Sequential)]636 public struct RECT637 {638 public uint left;639 public uint top;640 public uint right;641 public uint bottom;642 643 #region Properties644 public POINT Location645 {646 get { return new POINT((int)left, (int)top); }647 set648 {649 right -= (left - (uint)value.x);650 bottom -= (bottom - (uint)value.y);651 left = (uint)value.x;652 top = (uint)value.y;653 }654 }655 656 public uint Width657 {658 get { return right - left; }659 set { right = left + value; }660 }661 662 public uint Height663 {664 get { return bottom - top; }665 set { bottom = top + value; }666 }667 #endregion668 669 #region Overrides670 public override string ToString()671 {672 return left + ":" + top + ":" + right + ":" + bottom;673 }674 #endregion675 }676 #endregion677 678 #region WINDOWPOS679 [StructLayout(LayoutKind.Sequential)]680 public struct WINDOWPOS681 {682 public IntPtr hwnd;683 public IntPtr hwndAfter;684 public int x;685 public int y;686 public int cx;687 public int cy;688 public uint flags;689 690 #region Overrides691 public override string ToString()692 {693 return x + ":" + y + ":" + cx + ":" + cy + ":" + ((SWP_Flags)flags).ToString();694 }695 #endregion696 }697 #endregion698 699 #region NCCALCSIZE_PARAMS700 [StructLayout(LayoutKind.Sequential)]701 public struct NCCALCSIZE_PARAMS702 {703 public RECT rgrc1;704 public RECT rgrc2;705 public RECT rgrc3;706 public IntPtr lppos;707 }708 #endregion709 710 #region NMHDR711 [StructLayout(LayoutKind.Sequential)]712 public struct NMHDR713 {714 public IntPtr hwndFrom;715 public uint idFrom;716 public uint code;717 }718 #endregion719 720 #region OFNOTIFY721 [StructLayout(LayoutKind.Sequential)]722 public struct OFNOTIFY723 {724 public NMHDR hdr;725 public IntPtr OPENFILENAME;726 public IntPtr fileNameShareViolation;727 }728 #endregion
补充一下
1.代码只提供思路,不能拿来继承一下,就能实现自己想要的功能。
2.可以自己将代码中DialogNativeWindow类的addControl替换为其他控件,比如PictureBox用来预览图片、TextBox用来预览txt文件、RichTextBox用来预览代码文件等等,还可自由组合。
3.可以自己将代码中DialogNativeWindow类的两个事件(SelectedFileChanged、SelectPathChanged)移到MultiOpenFileDialog中,并使其对外开放,外部程序可以监听该事件。
4.如果想做成通用类,拿过来继承一下就可以实现自己想要的效果,建议使MultiOpenFileDialog从UserControl,并将addControl设为自己。也就是说将自己添加到OpenFileDialog中去,MultiOpenFileDialog的派生类就可以在VS中设计自己想要的效果。
5.一个窗体新建显示时,它的拥有者会接收许多消息,包括WM_ACTIVATE、WM_IDLE等等,并且Lparam参数为新建窗体的句柄。
1 class Form1:Form 2 { 3 private void Form1_Load(Object sender,EventArgs e) 4 { 5 using(OpenFileDialog dia = new OpenFileDialog()) 6 { 7 dia.ShowDialog(this); 8 } 9 }10 protected override void WndProc(ref Message m)11 {12 //当dia显示时,它的拥有者即为this,这里会接受一连串的Window消息,并且它的Lparam参数为dia的句柄13 base.WndProc(ref m);14 }15 }
6.Windows中窗体和所谓的控件(button、textbox)本质上没有区别,任务栏与QQ聊天框或者Chrome浏览器的地址栏对我们程序员来讲,是同一个东西。
7.与窗体有关的Win32 API基本都需要窗体句柄,其实任何一个API几乎都需要知道操作对象的句柄(不一定是窗体)。
8.Windows中任何一个窗体(控件)理论上都是平级的,不管是否同一进程,也就是说,我的winform应用程序只要知道了Chrome浏览器窗体的句柄,就可以控制Chrome浏览器,监听Chrome窗体的Windows消息(除非Chrome程序本身禁止了此操作)。
9.Windows桌面应用程序开发中,(部分平台、语言)理解四个东西,即进程、线程 、窗体(已经说了,是广义上的窗体)、消息。
10.查看系统中以上四个东西,可以使用Spy++工具。
完了,剩下那个下次再写了,太多了。希望有帮助~