try to use the Reflection tool to see how it is implemented
I mean, if you have infragistics control, you should be able to see the implementation with Lutz Roeder's Reflector tool, unless their assembly is obfusctaedhttp://www.aisto.com/roeder/dotnet/
网上到处都有DevExpress系列控件的源码,一窥便知。
'== Form1 添加 TextBox 和 CommandButton == Option Explicit Private Sub Command1_Click() Text1.SetFocus Form2.Action Text1 End SubPrivate Sub Text1_LostFocus() Unload Form2 End Sub'== Form2: borderstyle = 0, 添加 ListBox == Option Explicit Private Const SW_SHOWNOACTIVATE As Long = 4Private Type POINTL x As Long y As Long End TypePrivate Type RECT Left As Long Top As Long Right As Long Bottom As Long End TypePrivate Declare Function GetClientRect Lib "user32.dll" (ByVal hwnd As Long, ByRef lpRect As RECT) As Long Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Long, ByRef lpRect As RECT) As Long Private Declare Function ReleaseCapture Lib "user32.dll" () As Long Private Declare Function SetCapture Lib "user32.dll" (ByVal hwnd As Long) As Long Private Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long Private Declare Function PtInRect Lib "user32.dll" (ByRef lpRect As RECT, ByVal x As Long, ByVal y As Long) As LongPrivate mtxt As TextBoxPublic Sub Action(ByVal txt As TextBox) Dim rc As RECT
Set mtxt = txt GetWindowRect txt.hwnd, rc
Me.Enabled = False Me.Move rc.Left * Screen.TwipsPerPixelX, rc.Bottom * Screen.TwipsPerPixelY, (rc.Right - rc.Left) * Screen.TwipsPerPixelX, List1.Height ShowWindow Me.hwnd, SW_SHOWNOACTIVATE ReleaseCapture SetCapture Me.hwnd End SubPrivate Sub Form_Load() List1.AddItem "Item a" List1.AddItem "Item b" List1.AddItem "Item c" List1.AddItem "Item d" List1.AddItem "Item e" End SubPrivate Sub Form_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single) Dim rc As RECT Dim pt As POINTL Dim l As Long
GetClientRect List1.hwnd, rc pt.x = x / Screen.TwipsPerPixelX - 2 pt.y = y / Screen.TwipsPerPixelY - 2 If PtInRect(rc, pt.x, pt.y) Then l = pt.y \ (TextHeight("Item a") / Screen.TwipsPerPixelY) If l <= List1.ListCount - 1 Then mtxt = List1.List(l) End If End If ReleaseCapture Unload Me End SubPrivate Sub Form_Resize() List1.Move 0, 0, ScaleWidth, ScaleHeight End SubPrivate Sub Form_Unload(Cancel As Integer) Set mtxt = Nothing End Sub
} //---------------------------------------SystemShell类--------------------------------------------- public class SystemShell {
public const int GWL_STYLE = -16; public const int WS_VISIBLE =0x10000000; public const int WS_CHILDWINDOW = 0x40000000; public const int WS_CLIPSIBLINGS = 0x04000000; public const int WS_CLIPCHILDREN = 0x02000000; public const int WS_BORDER = 0x00800000; public const long WS_THICKFRAME = 0x00040000; public const long WS_OVERLAPPED = 0x00000000; public const int WM_NCPAINT = 0x0085; public const int WM_ACTIVATEAPP = 0x001C; [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern long SetWindowLong(IntPtr hWnd, int nIndex, long dwNewLong); [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern long GetWindowLong( IntPtr hWnd,int nIndex); [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern int SendMessage(IntPtr hWnd , int msg , int wParam ,int lParam ); [DllImport("user32.dll", CharSet=CharSet.Auto)] public static extern int GetWindowRect (IntPtr hWnd , ref System.Drawing.Rectangle lpRect); private SystemShell() { // // TODO: 在此处添加构造函数逻辑 // } } //-----------------------窗口2------------------------------------------- public class Form2 : System.Windows.Forms.Form { private System.Windows.Forms.Button button1; private System.Windows.Forms.ListBox listBox1; private System.Windows.Forms.TextBox textBox1; /// <summary> /// 必需的设计器变量。 /// </summary> private System.ComponentModel.Container components = null; public Form2() { // // Windows 窗体设计器支持所必需的 //
Option Explicit
Private Sub Command1_Click()
Text1.SetFocus
Form2.Action Text1
End SubPrivate Sub Text1_LostFocus()
Unload Form2
End Sub'== Form2: borderstyle = 0, 添加 ListBox ==
Option Explicit
Private Const SW_SHOWNOACTIVATE As Long = 4Private Type POINTL
x As Long
y As Long
End TypePrivate Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End TypePrivate Declare Function GetClientRect Lib "user32.dll" (ByVal hwnd As Long, ByRef lpRect As RECT) As Long
Private Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As Long, ByRef lpRect As RECT) As Long
Private Declare Function ReleaseCapture Lib "user32.dll" () As Long
Private Declare Function SetCapture Lib "user32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hwnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function PtInRect Lib "user32.dll" (ByRef lpRect As RECT, ByVal x As Long, ByVal y As Long) As LongPrivate mtxt As TextBoxPublic Sub Action(ByVal txt As TextBox)
Dim rc As RECT
Set mtxt = txt
GetWindowRect txt.hwnd, rc
Me.Enabled = False
Me.Move rc.Left * Screen.TwipsPerPixelX, rc.Bottom * Screen.TwipsPerPixelY, (rc.Right - rc.Left) * Screen.TwipsPerPixelX, List1.Height
ShowWindow Me.hwnd, SW_SHOWNOACTIVATE
ReleaseCapture
SetCapture Me.hwnd
End SubPrivate Sub Form_Load()
List1.AddItem "Item a"
List1.AddItem "Item b"
List1.AddItem "Item c"
List1.AddItem "Item d"
List1.AddItem "Item e"
End SubPrivate Sub Form_MouseDown(Button As Integer, Shift As Integer, x As Single, y As Single)
Dim rc As RECT
Dim pt As POINTL
Dim l As Long
GetClientRect List1.hwnd, rc
pt.x = x / Screen.TwipsPerPixelX - 2
pt.y = y / Screen.TwipsPerPixelY - 2
If PtInRect(rc, pt.x, pt.y) Then
l = pt.y \ (TextHeight("Item a") / Screen.TwipsPerPixelY)
If l <= List1.ListCount - 1 Then
mtxt = List1.List(l)
End If
End If
ReleaseCapture
Unload Me
End SubPrivate Sub Form_Resize()
List1.Move 0, 0, ScaleWidth, ScaleHeight
End SubPrivate Sub Form_Unload(Cancel As Integer)
Set mtxt = Nothing
End Sub
而且反编译以后也不是就一点代码,我看了很久没看明白啊。Tiger_Zhao(VB老鸟) ( )
哥们你的代码好像有点像、我明天到公司看看。
高定了你就是我今年第一大n人了。
不过我可以说一下,我在C里面实现这样的类似窗口只要把那个子窗口设置为WS_CHILD |WS_THIKFRAME|WS_VISBLE风格就可以了,不要加WS_POPUP. 我想点的那个窗口也应设置类似属性。
Form myForm = new myFormClass();myForm.Location = new Point(0,0);
myForm.TopLevel = false;
myForm.TopMost = false;
myForm.ControlBox = false;
myForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
myForm.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
myForm.Size = myFormPanel.ClientSize;
myForm.Parent = myFormPanel;
myForm.Visible = true;
不能用Panel.Controls.Add( myForm ),要使用Form.Visible
http://community.csdn.net/Expert/topic/3750/3750818.xml?temp=.7878076
问题的关键在于两个地方:
1、如何保证焦点一直保持在接受输入的窗口(控件)内
2、如何保证在输入 PAD 之外的地方有鼠标点击则隐藏该 PAD以下逐一解决:
1、不能使用系统的按钮控件,因为系统的按钮控件的实现中,一旦处理 WM_LBUTTONDOWN 消息,则会导致对该按钮调用 SetFocus()。解决的办法是自己写一个功能等同于按钮的控件,在处理 WM_LBUTTONDOWN 消息时不要调用 SetFocus() 函数即可,系统并不会自动将焦点转给你的控件
2、其实很简单,就在于调用 SetCapture()。如果对一个窗口调用了此函数,则在相应的 ReleaseCapture() 调用之前(同时也需要确保没有收到 WM_CAPTURECHANGED 消息),所有的鼠标点击消息都会被系统发送到该窗口,如果在此期间某一鼠标键还保持在按下状态,则鼠标移动消息也会被发送到该窗口。所以解决的办法是:PAD 显示时调用 SetCapture(),接收到鼠标点击消息时判断点击点是否位于 PAD 窗口内,如不是,则隐藏 PAD 窗口,在隐藏的同时调用 ReleaseCapture()。以上论述均基于 Windows 操作系统的 SDK 知识,我不会 C#,楼主可能需要自己去克服语言转换中的困难。但我敢保证,上述方法一定可以达到所要求的效果。祝好运。
private void button2_Click(object sender, System.EventArgs e)
{
Rectangle rect =Rectangle.Empty;
SystemShell.GetWindowRect(button2.Handle,ref rect);
Form2 f2= new Form2();
//胡乱到VC 搞了些 样式 放在上面竟然好使了
//最主要的好像是 WS_CHILDWINDOW
long Style = SystemShell.WS_VISIBLE | SystemShell.WS_CHILDWINDOW |
SystemShell.WS_CLIPSIBLINGS |SystemShell.WS_CLIPCHILDREN|
SystemShell.WS_BORDER| SystemShell.WS_THICKFRAME;
SystemShell.SetWindowLong(f2.Handle,SystemShell.GWL_STYLE,Style);
//设置 F2 的归属 这个也比较主要。
f2.Owner=this; //定位窗口的位置
f2.Left=rect.Left;
f2.Top=rect.Top+button2.Height;
f2.Visible=true; //这样的窗口好像出来后自己不刷新 只好自己刷了
SystemShell.SendMessage(f2.Handle,SystemShell.WM_NCPAINT,1,0);
f2.Invalidate();
}
//---------------------------------------SystemShell类---------------------------------------------
public class SystemShell
{
public const int GWL_STYLE = -16;
public const int WS_VISIBLE =0x10000000;
public const int WS_CHILDWINDOW = 0x40000000;
public const int WS_CLIPSIBLINGS = 0x04000000;
public const int WS_CLIPCHILDREN = 0x02000000;
public const int WS_BORDER = 0x00800000;
public const long WS_THICKFRAME = 0x00040000;
public const long WS_OVERLAPPED = 0x00000000;
public const int WM_NCPAINT = 0x0085;
public const int WM_ACTIVATEAPP = 0x001C; [DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern long SetWindowLong(IntPtr hWnd, int nIndex, long dwNewLong); [DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern long GetWindowLong( IntPtr hWnd,int nIndex);
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd , int msg , int wParam ,int lParam );
[DllImport("user32.dll", CharSet=CharSet.Auto)]
public static extern int GetWindowRect (IntPtr hWnd , ref System.Drawing.Rectangle lpRect); private SystemShell()
{
//
// TODO: 在此处添加构造函数逻辑
//
}
}
//-----------------------窗口2-------------------------------------------
public class Form2 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.TextBox textBox1;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null; public Form2()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
} /// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
} #region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.listBox1 = new System.Windows.Forms.ListBox();
this.textBox1 = new System.Windows.Forms.TextBox();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(192, 176);
this.button1.Name = "button1";
this.button1.TabIndex = 0;
this.button1.Text = "button1";
//
// listBox1
//
this.listBox1.ItemHeight = 12;
this.listBox1.Items.AddRange(new object[] {
"2222",
"3333",
"4444",
"5555",
"6666",
"7777",
"8888",
"9999"});
this.listBox1.Location = new System.Drawing.Point(40, 24);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(120, 52);
this.listBox1.TabIndex = 1;
//
// textBox1
//
this.textBox1.Location = new System.Drawing.Point(40, 136);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(184, 21);
this.textBox1.TabIndex = 2;
this.textBox1.Text = "textBox1";
//
// Form2
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(292, 273);
this.ControlBox = false;
this.Controls.Add(this.textBox1);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.button1);
this.Name = "Form2";
this.Load += new System.EventHandler(this.Form2_Load);
this.ResumeLayout(false); }
#endregion
private void Form2_Deactivate(object sender, System.EventArgs e)
{
this.Close();
} protected override void WndProc(ref Message m)
{
// TODO: 添加 Form2.WndProc 实现
if (m.Msg== SystemShell.WM_ACTIVATEAPP && m.WParam == IntPtr.Zero )
{
this.Dispose();
}
base.WndProc (ref m);
} private void Form2_Load(object sender, System.EventArgs e)
{
this.Owner.MouseDown+=new MouseEventHandler(Owner_MouseDown);
} private void Owner_MouseDown(object sender, MouseEventArgs e)
{
this.Dispose();
}
}
/*************************************************************************
先谢谢各位
现在基本上 几经很像了,唯一的问题就是 鼠标在 Form2 上
只有对 button 有用可以触发单击事件(但如果 Form2 捕捉鼠标 button 也不能点了)
1)listBox1 光可以拉动滚动条但无法 选中里面的 item。
2)textBox1 无法输入。
大家加油,
一起继续解决问题。最好那位朋友个封装个通用的类库,就爽了作个下拉 grid 什么的多方便啊。以上代码的-图:
http://www.kairuisoft.com/xz/image/Q/dpWinFrm.gif
以上代码的-代码:
http://www.kairuisoft.com/xz/image/Q/dpWinFrm.rar
*************************************************************************/