昨天写了《C# 实现假关机》,发现其中的办法对Win7不适应,还是会被强制关掉。今天想到另一种方法,在鼠标即将点击开始菜单关机按钮的时候,把鼠标的消息拦截下来,然后我们的程序收到这个消息,处理一下,比如关闭显示器,然后把消息丢弃掉,这样关机按钮的消息就收不到,自然就不会关机了。这样的好处是,系统收不到关机消息,自然没有强制关闭那个窗口了。

这里要用到钩子HOOK,需要用Form,完整代码如下:

using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;
 
namespace HookShutdown
{
    public partial class FormMain : Form
    {
        internal enum HookType
        {
            MsgFilter = -1,
            JournalRecord = 0,
            JournalPlayback = 1,
            Keyboard = 2,
            GetMessage = 3,
            CallWndProc = 4,
            CBT = 5,
            SysMsgFilter = 6,
            Mouse = 7,
            Hardware = 8,
            Debug = 9,
            Shell = 10,
            ForegroundIdle = 11,
            CallWndProcRet = 12,
            KeyboardLL = 13,
            MouseLL = 14
        }
        internal delegate IntPtr HookProc(int code, int wparam, IntPtr lparam);
        public struct POINT
        {
            public int x;
            public int y;
        }
 
        public struct MSLLHOOKSTRUCT
        {
            public POINT pt;
            public uint mouseData;
            public uint flags;
            public uint time;
            public int dwExtraInfo;
        }
 
        private IntPtr m_NextHookPtr = IntPtr.Zero;
        private IntPtr m_Handle = IntPtr.Zero;
        private IntPtr _handle = IntPtr.Zero;
        private uint trayWndThreadId = 0;
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);
        [DllImport("user32.dll", SetLastError = true)]
        static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("User32.dll")]
        static extern void UnhookWindowsHookEx(IntPtr handle);
        [DllImport("User32.dll", SetLastError = true)]
        static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc lpfn, IntPtr hMod, uint dwThreadId);
        [DllImport("User32.dll")]
        static extern IntPtr CallNextHookEx(IntPtr handle, int code, int wparam, IntPtr lparam);
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll")]
        static extern IntPtr WindowFromPoint(POINT Point);
        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
        [DllImport("kernel32.dll")]
        static extern uint GetLastError();
 
        [DllImport("user32.dll")]
        static extern bool BlockInput(bool fBlockIt);
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
 
        const UInt32 WM_SYSCOMMAND = 0x0112;
        const UInt32 SC_MONITORPOWER = 0xF170;
 
        public FormMain()
        {
            InitializeComponent();
 
            IntPtr hWnd = FindWindow("Shell_TrayWnd", (string)null);
            if (hWnd != IntPtr.Zero)
            {
                uint procID = 0;
                trayWndThreadId = GetWindowThreadProcessId(hWnd, out procID);
                InstallHook();//安装钩子
            }
        }
 
        ~FormMain()
        {
            UnInstallHook();//卸载钩子
        }
 
        private void InstallHook()
        {
            HookProc hookProc = new HookProc(IdentyFormHookProc);
            this.m_NextHookPtr = SetWindowsHookEx(HookType.MouseLL, hookProc, GetModuleHandle(
                        Process.GetCurrentProcess().MainModule.ModuleName
                        ), 0);
            //if(m_NextHookPtr == IntPtr.Zero)
            //    MessageBox.Show(GetLastError().ToString());
        }
        private void UnInstallHook()
        {
            if (this.m_NextHookPtr != IntPtr.Zero)
            {
                UnhookWindowsHookEx(this.m_NextHookPtr);
            }
        }
 
        private IntPtr IdentyFormHookProc(int code, int wparam, IntPtr lparam)
        {
            switch (wparam)
            {
                case (int)MsgType.WM_LBUTTONDOWN:
                case (int)MsgType.WM_LBUTTONUP:
                    MSLLHOOKSTRUCT msll = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lparam, typeof(MSLLHOOKSTRUCT));
                    IntPtr hWnd = WindowFromPoint(msll.pt);
                    if (hWnd != IntPtr.Zero)
                    {
                        uint procID = 0;
                        if (trayWndThreadId == GetWindowThreadProcessId(hWnd, out procID)) // 如果窗口线程是开始菜单所在的窗口线程
                        {
                            StringBuilder wndText = new StringBuilder(256);
                            GetWindowText(hWnd, wndText, 256);
                            if (wndText.ToString() == "关机") // 如果鼠标点击的是关机按钮
                            {
                                BlockInput(true);
                                SendMessage(this.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)2); // 关闭显示器
                                return (IntPtr)1;
                            }
                        }
                    }
                    break;
            }
            return CallNextHookEx(this.m_NextHookPtr, code, wparam, lparam);
        }
    }
}

注意:1.把开始菜单的电源按钮默认为 关机
2.要使得BlockInput这个函数有效,也就是在关闭显示器后中断鼠标键盘输入,程序要运行在管理员权限下
3.要恢复原有的关机,退出程序即可。

用HOOK实现Win7下假关机

阅读完本文,你将了解淘宝客链接劫持插件,并且你也可以自己制作一个Chrome版的链接劫持插件。笔者在去年用这种办法成功实现过,作为对阿里妈妈所谓开放平台和限制淘点金代码的不满,公开插件原理!

原理:这里需要一个客户端和一个服务端,客户端就是插件本身,服务端就是用于转换链接的网站,这里需要一个通过阿里妈妈验证的网站,假设网址为http://abc.com。客户端将淘宝单品的URL编码为一个URL参数,比如单品URL,然后和网站的网址组合成一个完整的新的URL,比如http://abc.com?url=单品URL,网站再将参数转换回原来的网址,利用淘点金或者淘宝客API实现转换,网站再重定向到转换完的推广网址上去就实现了劫持。这里有个问题,定向到推广链后淘宝那边会再次被定向回单品URL,这回已经不用再转换了,如何避免再次被插件劫持?有个办法,从推广链定向后的单品URL带有自己的PID,只要让插件在检测到这个PID的时候不再劫持就OK了!

Chrome劫持插件:这里假设你已经知道如何开发Chrome插件,并且了解background。我们使用chrome.tabs.onUpdated这个事件接口,就可以让插件在Chrome要打开新的URL时候得到通知,并且获得即将打开的URL。代码如下:

chrome.tabs.onUpdated.addListener(
	function(tabId, changeInfo, tab){
		var pid = "123456";  // 自己的PID
		var server = "abc.com";  // 服务器端的URL
 
		var u = purl(tab.url);  // 用purl解析即将打开的单品网址
		var host = u.attr('host'); // 获得网址的主机头
 
		if(host.indexOf(".taobao.com") == -1 &&
			host.indexOf(".tmall.com") == -1)
			return; // 判断是不是淘宝或者天猫的链接,如果不是,返回,不转换
 
		var new_id = u.param('id'); // 获得单品id
		var ali_trackid = u.param('ali_trackid'); // 获得PID
 
		if(ali_trackid != null) {
			if(ali_trackid.indexOf(pid) > 0)
				return; // 如果有PID,并且是自己的PID,返回,不转换
		}
		if(host == "item.taobao.com" ||
			(host == "detail.tmall.com" && u.attr('path') == "/item.htm")) {
 
			if(new_id == null ||
				old_id == new_id)
				return;
 
			old_id = new_id;
 
			var url_go = "http://";
			url_go += host;
			url_go += u.attr('path');
			url_go += "?id=";
			url_go += new_id; // 重新组合成URL
 
			chrome.tabs.update(tabId, {url:"http://" + server + "/index.php?url=" + encodeURIComponent(url_go)}); //定向到服务器端转换
		}
	}
);

服务器端代码:PHP,淘点金版

<html dir="ltr" lang="zh-CN">
<head>
	<meta charset="UTF-8" />
	<title></title>
	<script type="text/javascript" src="js/purl.js"></script>
</head>
<body>
	<a id="urlhref" href="<?php echo $_GET['url'];?>" target="_self" data-rd="1" data-other="spm:2013">..</a>
<script type="text/javascript">
(function(win,doc){
var s = doc.createElement("script"), h = doc.getElementsByTagName("head")[0];
if (!win.alimamatk_show) {
s.charset = "gbk";
s.async = true;
s.src = "http://a.alimama.cn/tkapi.js";
h.insertBefore(s, h.firstChild);
}
var o = {
pid: "mm_123456789_1234567_12345678",
appkey: "",
unid: "",
  rd:1
}
win.alimamatk_onload = win.alimamatk_onload || [];
win.alimamatk_onload.push(o);
})(window,document);
 
  function firemousedown(ctrl){
    if (document.createEvent){
      var e1 = document.createEvent('MouseEvent');
      e1.initEvent('mousedown', true, false);
      ctrl.dispatchEvent(e1);
    } else if (document.createEventObject) {
      var evtObj = document.createEventObject();
      evtObj.button = 0;
      ctrl.fireEvent('onmousedown', evtObj);
    }
  }
var old_event = document.onreadystatechange;
document.onreadystatechange = function(){
	function oncomplete(){
		if((/complete/.test(document.readyState))){
			document.onreadystatechange = null;
			if(old_event)
				old_event();
 
			var sub = document.getElementById("urlhref");
			var u = sub.href;
			if(u == null || u == '')
				window.location.replace("http://www.taobao.com");
 
			u = u.replace(/#[^&]*/g, "");
			u = u.replace(/ali_trackid=[^&]*/g, "");
			sub.href = u;
<?php if(isset($_GET["focus"]) && $_GET["focus"] == 1) {?>
			firemousedown(sub);
<?php } else {?>
			var url = purl(u);
			var host = url.attr('host');
			if(host == "item.taobao.com" ||
				(host == "detail.tmall.com" && url.attr('path') == "/item.htm")) {
 
				firemousedown(sub);
			} else {
				window.location.replace(sub.href);
				return;
			}
<?php }?>
			setTimeout(function(){
				if(sub.href.indexOf("click.taobao.com") > 0) {
					window.location.replace(sub.href);
				} else {
                  firemousedown(sub);
				}
			}, 40);
		} else {
			setTimeout(oncomplete, 40);
		}
	}
	oncomplete();
}
</script>
</body>

此段代码先从URL获得单品链接,然后写入标签的href属性中,再用js触发对的标签点击,按照淘点金的说明,这样会进行到推广链的转换,这样转换后就跳转到推广的网址了!如果你用过淘点金,你会马上分辨出中间的淘点金代码。

未完待续。。。

http://www.shenyaocn.com/?p=171 ‎

使用本代码,你可以实现在点下Windows关机键后,屏幕关闭,鼠标键盘暂时不能唤醒屏幕,让人以为已经关闭了电脑!
时间所限,仅列出关键代码,你可以在此基础上添加上显示假的关机屏幕,以实现以假乱真效果!

导入Win32 API三个函数

        [DllImport("kernel32.dll")]
        static extern bool SetProcessShutdownParameters(uint dwLevel, uint dwFlags); // 设置进程相对于其它进程的关闭优先级
        [DllImport("user32.dll")]
        static extern bool BlockInput(bool fBlockIt); // 禁用键盘鼠标
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); //用于发送关闭显示器消息
        const UInt32 WM_SYSCOMMAND = 0x0112;
        const UInt32 SC_MONITORPOWER = 0xF170;

下面是主要代码

        public FormMain()
        {
            InitializeComponent();
            Microsoft.Win32.SystemEvents.SessionEnding += SessionEndingEvent;
 
            SetProcessShutdownParameters(0x480, 0);
        }
 
        ~FormMain()
        {
            Microsoft.Win32.SystemEvents.SessionEnding -= SessionEndingEvent;
        }
 
        private void SessionEndingEvent(object sender, SessionEndingEventArgs e)
        {
            SessionEndReasons endReasons = e.Reason;
            BlockInput(true);
            SendMessage(this.Handle, WM_SYSCOMMAND, (IntPtr)SC_MONITORPOWER, (IntPtr)2);
            e.Cancel = true;
        }

注意:Microsoft.Win32.SystemEvents.SessionEnding事件需要在Form窗体下才有效,不然这么简单的程序我还是习惯写成控制台的。程序在接收到系统关机信息后,先用BlockInput切断键盘鼠标输入,然后关闭显示器。SetProcessShutdownParameters的目的是保证次程序最先收到关机消息。

如何恢复输入?MSDN说 Presse CTRL+ALT+DEL!

Win7 下是阻止不了关机的!Win7下可以参考这个 《用hook实现win7下假关机》

转载注明:http://www.shenyaocn.com/c-实现假关机/

Android4.0下用Activity作为对话框显示时,为了和让底部的按钮也同样拥有Holo对话框下的风格,只要将底部按钮的代码做如下修改:

 
    <View android:layout_width="fill_parent"
            android:layout_height="1dip"
            android:background="?android:attr/dividerHorizontal" />
    <LinearLayout
            style="?android:attr/buttonBarStyle"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:measureWithLargestChild="true"
            >
        <Button
                android:id="@+id/share"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/share"/>
        <Button
                android:id="@+id/edit"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/edit"/>
        <Button
                android:id="@+id/close"
                style="?android:attr/buttonBarButtonStyle"
                android:layout_width="0dip"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/close"/>
    </LinearLayout>

就OK了!
这是在编写桌面便签的语音播放界面时用到的。

转载注明 http://www.shenyaocn.com/?p=147

花了半周的时间重新编写了一个语音便签的播放界面,不再调用系统的播放器。自行编写的播放界面更灵活,可以分享语音便签,也可以对语音便签重新编辑,比如颜色,是否显示时间等,还可以重新录制语音!新版发布前把图标也改了,跟语音便签那个麦克风一样,变得扁平,风格更加统一!

“桌面便签” 4.0版的更新信息:
1. 新的语音播放界面
2. 语音便签支持分享
3. 支持重新编辑语音便签
4. 使用新的图标
5. 修复小尺寸语音便签点击无效
6. 修复部分BUGS

下载

Google Play 从应用汇下载