我想用c#实现“金山词霸-背单词”那样的效果,采用了使TransparencyKey同窗体背景色相同的办法,但窗体镂空后无法接收鼠标事件了,用了调用GetAsyncKeyState()检测鼠标状态,再发送消息的办法,实现也不理想,请问有没有更好的方法。
谢谢! 

解决方案 »

  1.   

    贴代码来看看吧,这样说不好说。
    不过可以肯定的是,是否透明 与 接受鼠标事件没有太直接的关系,
    重点就是看看代码中的消息处理函数,是否包 鼠标事件也处理掉了。
    比如:
    PreProcessMessage
    CreateParams     
      

  2.   

    利用mousedown和mousemove事件,当用户按下鼠标左键并拖动时,通过调用Form.Move即可拖动窗体。按下鼠标左键得到一个坐标,mousemove事件中得到一个新坐标,两坐标相减,得到了窗体移动的位移。
      

  3.   

    我记得有人说过纯的透明要用directX才能做。
    GDI+是不行的。所以为了简单的话, 他们会用WPF。
      

  4.   

    真是谢谢各位。这个问题自己想办法解决了。
    其实之前是想复杂了,使用TransparencyKey()后窗体是不能接收鼠标消息了。但可以用一个定时器检测鼠标位置,判断是否在窗体内,若在窗体内且鼠标左键按下,便发送HTCAPTION消息给窗体模拟鼠标拖动标题栏即可。
    google了一下,也有这种说法:
    首先必须了解Windows的消息传递机制,当有鼠标活动消息时,系统发送WM_NCHITTEST 消息给窗体作为判断消息发生地的根据。假如你点击的是标题栏,窗体收到的消息值就是 HTCAPTION ,同样地,若接受到的消息是 HTCLIENT,说明用户点击的是客户区,也就是鼠标消息发生在客户区。当重载窗体的 WndProc 方法时,可以截获 WM_NCHITTEST 消息并改些该消息,当判断鼠标事件发生在客户区时,改写改消息,发送 HTCAPTION 给窗体,这样,窗体收到的消息就时 HTCAPTION ,在客户区通过鼠标来拖动窗体就如同通过标题栏来拖动一样。具体实现如下:
    void TimerTick(object sender, EventArgs e)
    {
    //先设定浮动区域是否可以响应鼠标事件
    Point pt = new Point(MousePosition.X, MousePosition.Y);
    if(this.Bounds.Contains(pt))
    {
    //先改变背景
    this.BackColor = Color.GhostWhite;

    Control control =new Control();
    if(GetAsyncKeyState(VK_LBUTTON) < 0)
    {
    ReleaseCapture();
    SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    }

    }
    else
    this.BackColor = Color.White;
    }其中需要引用dll:
    [DllImport("user32.dll")]
    private extern static int GetAsyncKeyState(int nIndex);
    [DllImport("User32.dll",EntryPoint="SendMessage")]
    private extern static int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
    [DllImport("user32.dll")]   
    public static  extern bool ReleaseCapture();