想用C#做一个能够透明+鼠标透过的窗口,遇到一些问题
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Diagnostics;
namespace Easy
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public delegate int HookProc(int nCode, int wParam, IntPtr lParam);
static int hHook = 0;
public const int WH_KEYBOARD_LL = 13;
HookProc KeyBoardHookProcedure;
private void Form1_Load(object sender, EventArgs e)
{
this.Opacity = 0.8;
this.TopMost = true;
this.ShowInTaskbar = true;
this.WindowState = FormWindowState.Normal;
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0, 128, LWA_ALPHA);
}
[StructLayout(LayoutKind.Sequential)]
public class KeyBoardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
#region DllImport
//设置钩子
[DllImport("user32.dll")]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
//抽掉钩子
public static extern bool UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll")]
//调用下一个钩子
public static extern int CallNextHookEx(int idHook, int nCode, int wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId();
[DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
public static extern long GetWindowLong(IntPtr hwnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
public static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
[DllImport("user32", EntryPoint = "SetLayeredWindowAttributes")]
public static extern int SetLayeredWindowAttributes(IntPtr Handle, int crKey, byte bAlpha, int dwFlags);
const int GWL_EXSTYLE = -20;
const int WS_EX_TRANSPARENT = 0x20;
const int WS_EX_LAYERED = 0x80000;
const int LWA_ALPHA = 2;
#endregion
#region 自定义事件
public void Hook_Start()
{
// 安装键盘钩子
if (hHook == 0)
{
KeyBoardHookProcedure = new HookProc(KeyBoardHookProc);
hHook = SetWindowsHookEx(WH_KEYBOARD_LL,
KeyBoardHookProcedure,
GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
if (hHook == 0)
{
Hook_Clear();
//throw new Exception("设置Hook失败!");
}
}
}
//取消钩子事件
public void Hook_Clear()
{
bool retKeyboard = true;
if (hHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hHook);
hHook = 0;
}
//如果去掉钩子失败.
if (!retKeyboard) throw new Exception("UnhookWindowsHookEx failed.");
}
public static int KeyBoardHookProc(int nCode, int wParam, IntPtr lParam)
{
if (nCode >= 0)
{
KeyBoardHookStruct kbh = (KeyBoardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyBoardHookStruct));
if (kbh.vkCode == (int)Keys.Y && (int)Control.ModifierKeys == (int)Keys.Control + (int)Keys.Alt)
{ MessageBox.Show("x");
SetWindowLong(lParam, GWL_EXSTYLE, GetWindowLong(lParam, GWL_EXSTYLE));
}
}
return CallNextHookEx(hHook, nCode, wParam, lParam);
}
private void button1_Click(object sender, EventArgs e)
{
Hook_Start();
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) | WS_EX_TRANSPARENT | WS_EX_LAYERED);
}
private void button2_Click(object sender, EventArgs e)
{
Hook_Clear();
}
}
}
#endregion
这个程序有两个问题
1,全局钩子用快捷键呼出后,出弹出两次消息框,而且第一次消息框很快弹出,第二个就要等3s左右
2,通过快捷键取消透明+透过无效
麻烦各位大大帮我分析一下,谢谢
--------------------编程问答-------------------- 不懂,帮顶 --------------------编程问答-------------------- --------------------编程问答-------------------- 有这么麻烦么?把窗体this.TransparencyKey设为Transparent
里面随便于放一个控件,如RICHTECTBOX,WEBBRER什么的。而且透过窗口一点问题都没有。 --------------------编程问答--------------------
透明倒是没太大的问题,使之也穿透没问题。但是用快捷键获取窗口焦点的时候(即取消穿透)却失败了,求实现的具体...
我想达到的效果是
1,正常情况下置于顶层;鼠标穿透窗口无法获取窗口焦点;
2,需要操作窗口时通过全局快捷键获取其焦点,可以控制该窗口,此时无法鼠标穿透窗口
3,当不需要的时候通过快捷键使其恢复状态1 --------------------编程问答-------------------- 关注一下 --------------------编程问答-------------------- 鼠标都能透过,那怎么玩呢。 --------------------编程问答-------------------- --------------------编程问答-------------------- 取消穿透的时候你你把下面一个窗体隐藏试一下, --------------------编程问答-------------------- 正常情况下置于顶层;鼠标穿透窗口无法获取窗口焦点;
这个功能实现,建议使用拷贝软件界面直接写到屏幕上,这样就不存在问题。 --------------------编程问答-------------------- 我有现成代码,晚上给你。 --------------------编程问答--------------------
所以需要一个快捷键让窗口还原,否则确实没法操作 --------------------编程问答-------------------- 全局的快捷键 可以用 注册系统热键 的方式嘛! --------------------编程问答-------------------- 1,全局钩子用快捷键呼出后,出弹出两次消息框,而且第一次消息框很快弹出,第二个就要等3s左右
-- 这个主是要因为keyboard有两个事件,key_down 和 key_up,所以你会看到两个消息框弹出 --------------------编程问答-------------------- --------------------编程问答-------------------- if (kbh.vkCode == (int)Keys.Y && (int)Control.ModifierKeys == (int)Keys.Control + (int...
--觉得这行代码应该有点问题,会碰到优先级的问题,最好写成if (kbh.vkCode == (int)Keys.Y && ((int)Control.ModifierKeys == (int)Keys.Control + (int...)),可以试着看一下 --------------------编程问答--------------------
原来是这样,忽略了这点,谢谢了
现在问题主要在于如何恢复窗口的焦点和无法穿透。
我重新写了代码,这样清晰多了,但仍是出现提示框,无法更改窗口状态,是不是API用得不对,起初怀疑是窗口指针没获取正确,把窗口指针设为全局变量放进去仍失败,求指点
--------------------编程问答-------------------- 最好截个图 说明一下,就能理解你的意思了。
public partial class Form1 : Form
{//钩子API
[DllImport("user32.dll")]
public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint control, Keys vk);
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
//窗口API
[DllImport("user32.dll", EntryPoint = "GetWindowLong")]
public static extern long GetWindowLong(IntPtr hwnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "SetWindowLong")]
public static extern long SetWindowLong(IntPtr hwnd, int nIndex, long dwNewLong);
[DllImport("user32", EntryPoint = "SetLayeredWindowAttributes")]
public static extern int SetLayeredWindowAttributes(IntPtr Handle, int crKey, byte bAlpha, int dwFlags);
const int GWL_EXSTYLE = -20;
const int WS_EX_TRANSPARENT = 0x20;
const int WS_EX_LAYERED = 0x80000;
const int LWA_ALPHA = 2;
IntPtr ip;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ip = this.Handle;
this.Opacity = 0.8;
this.TopMost = true;
this.ShowInTaskbar = true;
this.WindowState = FormWindowState.Normal;
RegisterHotKey(this.Handle, 225, 0, Keys.X);
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) |WS_EX_TRANSPARENT| WS_EX_LAYERED);
SetLayeredWindowAttributes(Handle, 0, 128, LWA_ALPHA);
}
protected override void WndProc(ref Message m)
{
if (m.WParam.ToString().Equals("225"))
{
SetWindowLong(ip, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE));
MessageBox.Show("X"); }
base.WndProc(ref m);
}
补充:.NET技术 , C#