[转载]通过COM组件在Web上实现Kinect骨骼追踪、声控截屏保存的功能

mikel阅读(1070)

[转载]通过COM组件在Web上实现Kinect骨骼追踪、声控截屏保存的功能 – Leepy – 博客园.

前些天在淘宝上订购了Kinect,刚刚到货,对于这个新鲜的玩意儿,自己赶紧卸开包裹,插上PC机,先前已经装好了Kinect SDK(官方下载地址:http://research.microsoft.com/en-us/um/redmond/projects/kinectsdk/download.aspx

4caedc7aga62f734b0791&690

希望自己的机子能够跑得动DEMO,最后送了一口气,正常运行:)。当然了,既然Kinect已经入手,自己打算也小小地练一下手,因为自己目前主要从事Web方面的开发,自然想到,如果能够在网页上能够运行Kinect该有多好啊!后来考虑了三种方案:

1)在Web应用程序上引用Kinect SDK的DLL(Microsoft.Research.Kinect.dll),可以正常引用,通过img标签或者页面输出图像流的方式显示 Bitmap图像,当然你还需要定时刷新页面,当然这种方式的缺点可想而知,就是不够实时性。并且增加了服务器的负担。

2)通过Silverlight应用程序的方式,但是目前SL4/5均不支持Kinect的dll,这是由于Kinect是个.Net Framework的类库,非SL支持的客户端类库。另外,在非OOB的模式下,也SL目前不支持自定义的COM组件,希望微软团队将来能够让SL也支持 Kinect。

3)通过ActiveX的COM组件技术,通过开发窗体组件,产生ActiveX插件,嵌套在IE浏览器中进行显示。

于是,我考虑了最简单的方式,通过ActiveX的技术在网页上对Kinect相关基本功能进行展示。

本文会分成三个部分来叙述:

一、ActiveX插件的实现;

二、Kinect基本功能的实现;

三、ActiveX的安装;

具体实现

第一部分  ActiveX插件的实现

1) 创建一个新的解决方案,叫做MyFirstKinect。

2)接着创建一个Windows窗体控件库,用于做ActiveX的插件,项目叫做MyFirstKinectControl

image

3)在MyFirstKinectControl项目的右键点击“属性”,选择“生成”项:

image

将”为COM互操作注册”勾上,然后关闭。

4)打开AssemblyInfo.cs:

image

将ComVisible设置为true,并将下面这行注释掉(这个很重要,切记!

对应地,需要在自定义窗体控件上加上该Guid:

image

至此,一个基本的COM组件已经实现了,现在来看下该如何在浏览器上显示ActiveX插件。

5)打开Visual Studio的命令提示符:输入“oleview”,页面会打开一个“OLE/COM Object Viewer”应用程序:

image

由于我是使用C#创建的COM组件,于是在“.NET Category”寻找刚才创建的”MyFirstKinectControl”:

image

右键选择“Copy HTML<object> Tag to Clipboard”,得到:

image

6)然后我在自定义窗体控件上(SkeletalControl.cs),随便加入点东西上去,比如按钮、标签等等。

7)然后新创建一个Web应用程序的项目(WebApp),重新编译。将上面的代码复制到Html或相关页面中。

image

在IE正常状态下,发现插件无法正常显示。于是,把浏览器的安全级别调低:

image

继续运行:

image

就可以正常显示插件了。当然这种方式造成了浏览器使用上的危害性,所以不建议这样来使用。

8)如果想要在不调整浏览器安全级别的情况下,又能够在浏览器上正常显示插件,这样就必须调整一些代码:

[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}

添加一个IObjectSafety的接口,并且Guid是固定的。

SkeletalControl继承这个接口:

[Guid("d678c286-b26f-4f72-ae22-2dcb1952851b")]
public partial class SkeletalControl : UserControl, IObjectSafety
{
public SkeletalControl()
{
InitializeComponent();
}

#region IObjectSafety 成员

public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
}

public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)
{

}

#endregion
}

接着重新编译并运行Web程序,运行结果为:

image

这样,你就不需要调整浏览器的安全级别,就可以正常显示ActiveX插件了。

第二部分 Kinect的基本功能实现

从这一部分起,我将开始介绍Kinect如何实现一些基本功能:包括视频监控、骨骼追踪以及声控截屏的功能。

1)项目中引用以下的Dll:

image

其中Microsoft.Research.Kinect就是在电脑上装好Kinect SDK后可以引用的类库;

另外地,Coding4Fun.Kinect.WinForm是一个基于SDK的DLL的相关封装好的一些功能类库,网上开源地址为:http://c4fkinect.codeplex.com/

Microsoft.Speech是一个微软提供的语音识别的基本类库,也包含相关的SDK,并且和Kinect进行绑定的相关类库,具体地址在Kinect SDK中的相关文档也有说明:

– Speech Platform Runtime (v10.2) x86. Even on x64 platforms the x86 needs to be used because the MSR Kinect SDK runtime is x86
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=bb0f72cb-b86b-46d1-bf06-665895a313c7
– Speech Platform SDK (v10.2)
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=1b1604d3-4f66-4241-9a21-90a294a5c9a4&displaylang=en
– Kinect English Language Pack: MSKinectLangPack_enUS.msi (available in the same location as the Kinect For Windows SDK)

2)在控件页面上创建三个PictureBox的控件:

image

三个图片框将分别用来存放:深度图视频、普通视频、以及骨骼追踪。

3)编写相关代码:

using Microsoft.Research.Kinect.Nui;
using Coding4Fun.Kinect.WinForm;

Runtime nui;

private void SkeletalControl_Load(object sender, EventArgs e)
{
nui = new Runtime();

try
{
nui.Initialize(
RuntimeOptions.UseDepthAndPlayerIndex
| RuntimeOptions.UseSkeletalTracking
| RuntimeOptions.UseColor);
}
catch (InvalidOperationException)
{
MessageBox.Show("Runtime initialization failed. Please make sure Kinect device is plugged in.");
return;
}

try
{
nui.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
nui.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
}
catch (InvalidOperationException)
{
MessageBox.Show("Failed to open stream. Please make sure to specify a supported image type and resolution.");
return;
}

nui.DepthFrameReady += new EventHandler(nui_DepthFrameReady);
nui.SkeletonFrameReady += new EventHandler(nui_SkeletonFrameReady);
nui.VideoFrameReady += new EventHandler(nui_VideoFrameReady);
}

其中DepthFrameReady,VideoFrameReady,SkeletonFrameReady分别用来追踪深度图、普通视图、骨骼图所产生的事件。

void nui_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
{
pictureBoxDepth.Image = e.ImageFrame.ToBitmap();
}

void nui_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
{
pictureBoxVideo.Image = e.ImageFrame.ToBitmap();
}

void nui_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
Graphics graphics = this.pictureBoxSkeleton.CreateGraphics();

pictureBoxSkeleton.Refresh();

SkeletonFrame skeletonFrame = e.SkeletonFrame;
int iSkeleton = 0;

foreach (SkeletonData data in skeletonFrame.Skeletons)
{
if (SkeletonTrackingState.Tracked == data.TrackingState)
{
// Draw bones
graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.HipCenter, JointID.Spine, JointID.ShoulderCenter, JointID.Head));
graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.ShoulderCenter, JointID.ShoulderLeft, JointID.ElbowLeft, JointID.WristLeft, JointID.HandLeft));
graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.ShoulderCenter, JointID.ShoulderRight, JointID.ElbowRight, JointID.WristRight, JointID.HandRight));
graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.HipCenter, JointID.HipLeft, JointID.KneeLeft, JointID.AnkleLeft, JointID.FootLeft));
graphics.DrawLines(pen, getBodySegment(data.Joints, JointID.HipCenter, JointID.HipRight, JointID.KneeRight, JointID.AnkleRight, JointID.FootRight));
}
iSkeleton++;
} // for each skeleton
}

private Point getDisplayPosition(Joint joint)
{
float depthX, depthY;
nui.SkeletonEngine.SkeletonToDepthImage(joint.Position, out depthX, out depthY);
depthX = Math.Max(0, Math.Min(depthX * 320, 320));  //convert to 320, 240 space
depthY = Math.Max(0, Math.Min(depthY * 240, 240));  //convert to 320, 240 space
int colorX, colorY;
ImageViewArea iv = new ImageViewArea();
// only ImageResolution.Resolution640x480 is supported at this point
nui.NuiCamera.GetColorPixelCoordinatesFromDepthPixel(ImageResolution.Resolution640x480, iv, (int)depthX, (int)depthY, (short)0, out colorX, out colorY);

// map back to skeleton.Width &amp; skeleton.Height
return new Point((int)(this.pictureBoxSkeleton.Width * colorX / 640.0), (int)(this.pictureBoxSkeleton.Height * colorY / 480));
}

Point[] getBodySegment(Microsoft.Research.Kinect.Nui.JointsCollection joints, params JointID[] ids)
{
Point[] points = new Point[ids.Length];
for (int i = 0; i &lt; ids.Length; ++i)
{
points[i] = getDisplayPosition(joints[ids[i]]);
}

return points;
}

其中,getBodySegment,getDisplayPosition方法将确定骨骼追踪中的20个骨骼点的具体位置。

4)接着编译并运行程序,查看Web页面,连上Kinect传感设备,运行结果为:
image

5)接着,来实现一些声控截屏功能:

using Microsoft.Research.Kinect.Audio;
using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;

private const string RecognizerId = "SR_MS_en-US_Kinect_10.0";
private KinectAudioSource kinectSource;
private SpeechRecognitionEngine sre;

// 声控截屏功能
RecognizerInfo ri = SpeechRecognitionEngine.InstalledRecognizers().Where(r =&gt; r.Id == RecognizerId).FirstOrDefault();
if (ri == null)
{
MessageBox.Show("Could not find speech recognizer: {0}. Please refer to the sample requirements.", RecognizerId);
return;
}

sre = new SpeechRecognitionEngine(ri.Id);

var colors = new Choices();
colors.Add("cut"); //添加cut的英文发音

var gb = new GrammarBuilder();
gb.Culture = ri.Culture; //本地化处理
gb.Append(colors);

var g = new Grammar(gb);

sre.LoadGrammar(g);
sre.SpeechRecognized += SreSpeechRecognized;                    //发音匹配以后的后续处理事件
sre.SpeechHypothesized += SreSpeechHypothesized;                //发音的英文识别事件
sre.SpeechRecognitionRejected += SreSpeechRecognitionRejected;  //拒绝之后的后续处理事件

var thread = new Thread(StartDMO);
thread.Start();

private void StartDMO()
{
kinectSource = new KinectAudioSource();
kinectSource.SystemMode = SystemMode.OptibeamArrayOnly;
kinectSource.FeatureMode = true;
kinectSource.AutomaticGainControl = false;
kinectSource.MicArrayMode = MicArrayMode.MicArrayAdaptiveBeam;
var kinectStream = kinectSource.Start();
sre.SetInputToAudioStream(kinectStream, new SpeechAudioFormatInfo(
EncodingFormat.Pcm, 16000, 16, 1,
32000, 2, null));
sre.RecognizeAsync(RecognizeMode.Multiple);
}

void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
{

}

void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
{

}

void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
lblSpeech.Text = e.Result.Text;

//屏幕截屏
Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
Graphics g = Graphics.FromImage(bmp);
g.CopyFromScreen(0, 0, 0, 0, bmp.Size);
g.Dispose();

SaveFileDialog fileDialog = new SaveFileDialog();
fileDialog.Filter = "JPG File(*.jpg)|*.jpg||";
DialogResult result = fileDialog.ShowDialog();
if (result == DialogResult.OK)
{
bmp.Save(fileDialog.FileName, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}

在代码中发现,var colors = new Choices(); colors.Add(“cut”); //添加cut的英文发音 ,这样当你在传感器前发音“cut”就会进行相关事件的触发,当发音和英文库的单词语音识别向匹配时,将触发SreSpeechRecognized事 件。

执行屏幕截图的相关操作。

(注:记得这里需要添加代码gb.Culture = ri.Culture; 如果没有这句代码,有可能导致sre.LoadGrammar(g); 语法加载失败!)

6. 运行结果:

image

我将刚才发的英文单词,通过文本的方式显示在页面中。

第三部分 ActiveX插件的安装

由于本文使用的是C#来开发ActiveX插件,所以当你需要安装插件的时候,需要使用regasm命令。那么开始编写脚本:

1)安装脚本:

@echo off
echo 开始安装MyFirstKinectControl......
echo.
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.5
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.0
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v1.1.4322
if exist "%FrameworkPath%\regasm.exe" goto :Startv
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\1.0.3705
if exist "%FrameworkPath%\regasm.exe" goto :Start

:Start
%FrameworkPath%\regasm.exe MyFirstKinectControl.dll /codebase MyFirstKinectControl.dll

echo 安装完成!
echo.

pause

2)卸载脚本:

@echo off
echo 开始卸载MyFirstKinectControl......
echo.
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.5
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v3.0
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727
if exist "%FrameworkPath%\regasm.exe" goto :Start
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\v1.1.4322
if exist "%FrameworkPath%\regasm.exe" goto :Startv
set FrameworkPath=%SystemRoot%\Microsoft.NET\Framework\1.0.3705
if exist "%FrameworkPath%\regasm.exe" goto :Start

:Start
%FrameworkPath%\regasm.exe /u MyFirstKinectControl.dll

echo 卸载完成!
echo.

pause

这样通过注册COM组件就可以实现Kinect的插件在浏览器上的展示。

附上本文的源代码:MyFirstKinect.rar 谢谢大家阅读!

[转载]擦亮自己的眼睛去看SQLServer之简单Select

mikel阅读(984)

[转载]擦亮自己的眼睛去看SQLServer之简单Select – 小军人 – 博客园.

这 篇文章主要和大家讨论几乎所有人都熟悉,但不少人又陌生的一条select语句。不知道大家有没有想过到底是什么东西让SQLServer能理解我们写的 select。这中间到底发生了什么,是不是有过冲动想去了解。至少我曾经冲动想去了解,但当时主要在研究CLR以及webform相关知识。后来主要精 力放在研究SQLServer内部机制,今天就给大家介绍下这条语句。

一、范例数据库脚本

create database Test

go
alter database Test set recovery simple
go
use Test
go

create table Test

(
ID int identity(1,1) primary key,
[Name] varchar(64) not null default ”,
CreatedTime datetime not null default getdate()
)

insert into Test([name]) values(‘xiaojun’)

这个脚本就不介绍了,很简单。

二、语句分析

select * from Test

简单吧,本来嘛标题就是之简单语句。下面开始分析这条语句吧,假设读者已经知道了SQLServer整体架构或者已经阅读过这个系列第一篇文章。当这条语句被可靠的传递到关系引擎中的命令分析器,接下来就发生了:

分析:从语法库中检查T-SQL进行基本的语法检查。如果语法出错了,那整个语句就立即停止,提示用户语法出错,哪出错。比如错误使用的关键字、列、表名等。如果语法没有出错,就会生成一个分析树传递给下一个步骤。

绑定1、名字解析:检查所有的对象在用户的安全上下文中存在并可见。这个步骤很好理解主要是数据库每个对象都有权限。如果登录的账号没有相应权限,就结束这个步骤。

2、 类型推导:确定解析树中每个节点的最终类型。这个步骤主要是补充分析分析步骤中的分析树,确定其最终的类型。不知道大家可想过为什么要到这一步才确定。为 什么不在分析中确定呢?主要原因是效率,类型推导会消耗资源,没有必要在没有确定用户对每个对象有权限的情况下确定。那为什么不直接先确定用户对每个对象 有权限再做分析呢。那是因为没做分析的时候,系统无法知道具体有哪些对象。我又要说了,SQLServer的设计真的可以说是很精致的,连这样的细节和资 源消耗都考虑了。值得我们学习哦。

3、聚合绑定:确定哪些地方可以进行聚合。这个步骤主要和SQL中是否有聚合操作有关系。

4、组合绑定:将聚合绑定到正确的选择列表中。这个步骤是把聚合操作与需要聚合的列绑定对应起来。

这两步操作主要是由命令分析器完成,它最终得到分析树,传递给SQLServer引擎中最复杂最优技术含量的组件,没有之一,查询优化器。查询优化器功能概况起来很简单,就是优化SQL。具体优化模型如下:

优化:1、检查执行计划缓存中是有没对应的执行计划。 如果没有,继续下面操作。如果有则使用缓存。SQLServer是根据SQL的哈希值比较的。想想为什么?

2、预优化:查询语句很简单,开销足够小,直接结束优化。比如没有联接的基本查询。属于零开销,称为普通计划。比如我们这的select语句预优化就搞定了。

3、阶段0:检验基本规则,以及散列和嵌套联接选项。这个计划的开销是否小于0.2,如果是,结束优化。这里的0.2以及下面的1.0,这是SQLServer内部的开销值,仅供SQLServer系统内部使用。

4、阶段1:检验更多的规则,以及变换联接的顺序。如果开销最小的计划的开销小于1.0,如果是,结束优化。如果不是,继续判断。如果maxdop>0且这个系统是SMP系统,以及最小开销大于并行化的开销临界值,则使用并行计划。比较并行计划的开销和最好的串行计划的开销,将开销更小的计划传递给阶段2

并行计划是指优化器根据情况,将恰当的操作符拆分为数个可以同步运行的进程在不同的处理器上运行,需要多核支持。对于大数据量查询可以提高效率。

maxdop是什么呢?这是SQLServer的一个高级配置。我们可以通过sp_configure查看。如下图:

可能你直接运行sp_configure,看不到这个配置。主要是这是个高级配置项,默认不开启。你运行以下语句后再运行sp_configure就能看到以上图中信息。

sp_configure ‘show advanced options’,1

reconfigure

这里面的高级配置值,默认情况下不需要修改。必须你对SQLServer有较深理解,以及在修改前做好修改对整个SQLServer的影响的评估后才去改 动。说说这个maxdop吧,这是说SQLServer在执行并行计划的最大处理器数目,0代表由SQLServer决定。否则就是按照用户指定的最大并 行度。因此上面的maxdop>0且这个系统是SMP系统的意思就是当用户修改了这个配置项,那么执行器在评估开销时要优先考虑用户修改过的最大并行度小的系统开销。SMP系统是对称处理器体系结构,基于Intel处理器的服务器基本上都是SMP系统。在此不展开说。

不知道大家注意到没,我上面的图查询优化器输出的是较好的执行计划。想想为什么? 如果想查看优化过程的内部情况,可以使用一下sys.dm_exec_query_optimizer_info动态管理视图。比如,下面演示证明我们这条select语句是属于普通计划。按照如下操作执行:

dbcc freeproccache –清空执行计划缓存

select * from sys.dm_exec_query_optimizer_info where counter in(‘optimizations’,’trivial plan’,’search 0′,’search 1′,’search 2′)

结果如下:

继续:

select * from Test

select * from sys.dm_exec_query_optimizer_info where counter in(‘optimizations’,’trivial plan’,’search 0′,’search 1′,’search 2′)

结果如下:

发现了吧,trival plan类型计数+1,说明优化器对select * from Test进行优化时是普通计划。

5、阶段2:检验所有可能的计划,并且选择达到检验的时间限制时开销最小的计划。

执行:这个计划被调度执行,这个涉及到SQLOS不在本篇文章讨论范围,只要先简单理解为交给CPU执行。

三、结尾

其中这个语句还有很多地方可以分析,比较在这条语句执行时,加锁以及如何被调度执行。这些还是希望在放在后面的章节中解释。这篇文章主要是谈到了 SQLServer如何对SQL进行解析优化的。仔细研究,你会发现SQLServer的查询优化器做了很多优化措施当然其他数据库也类似的组件。其实你 会发现这些对于我们大部分开发人员都是屏蔽的。屏蔽是一种进步,java、.net的垃圾回收屏蔽了开发人员对内存的管理,那SQLServer在这里屏 蔽了什么呢,这需要研究数据库历史。只有研究历史,才能站在一个较高的角度知道现在的数据库为什么是现在的样子

今天分析就到此结束,文中如有描述不当的地方,欢迎指出。共同进步才是硬道理。

列下下一步六篇文章计划

擦亮自己的眼睛去看SQLServer之历史渊源

擦亮自己的眼睛去看SQLServer之数学基石

擦亮自己的眼睛去看SQLServer之简单insert

擦亮自己的眼睛去看SQLServer之实用索引

擦亮自己的眼睛去看SQLServer之锁机制

擦亮自己的眼睛去看SQLServer之纠结的Tempdb

[转载]打造最好用的离线QQ截图工具 C#

mikel阅读(1172)

[转载]打造最好用的离线QQ截图工具 C# – mengdesen – 博客园.

截图是最经常用的工具,QQ截图是我见过最好的截图工具,只是你必须打开QQ才可以使用,有时候没法上网,或者不想上QQ的时候,截图还是很麻烦。 Windows自带的那个截图工具和QQ的截图工具相差甚远。所以想找一个QQ离线时候的替代品。下了几个软件,觉得使用不够方便。最后找到了QQ截图工 具的提取版,可以实现QQ的截图功能,但是使用起来每次都带打开,而且不能使用快捷键。所以打算写个软件,重新整合一下。

要实现的功能

1:实现QQ的截图功能

2:时刻在后台运行,随时使用

3:不与QQ冲突

4:可以使用快捷键

5:开机自动启动

代码实现

1:实现QQ的截图功能,调用提取出来的程序

///

/// 启动外部程序,通过事件监视其退出

///

public void start_nokill()

{

// 启动外部程序

Process proc = Process.Start(appName);

IfExit = false;

if (proc != null)

{

// 监视进程退出

proc.EnableRaisingEvents = true;

// 指定退出事件方法

proc.Exited += new EventHandler(proc_Exited);

}

}

///

/// 启动外部程序退出事件

///

void proc_Exited(object sender, EventArgs e)

{

IfExit = true;

}

}

3:不与QQ冲突,如果用户启动QQ停止使用

///

/// 获取某进程是否存在

///

///
<span> </span>进程名

/// 是否存在

bool getPName(string PName)

{

Process[] processes = Process.GetProcesses();

foreach (Process p in processes)

{

if (p.ProcessName == PName)

{

return true;

}

}

return false;

}

private void timer_Tick(object sender, EventArgs e)

{

if (getPName("QQ") &amp;&amp; cbox_active.Checked)

{

cbox_active.Checked=false;

}

else if (!getPName("QQ"))

{

cbox_active.Checked = true;

}

}

4:可以使用快捷键

这部分是这个软件最难得地方,使用的是全局钩子,代码我是参考网上找到的,比较复杂,代码较长,有兴趣的点击下载代码

5:开机自动启动

///

/// 设置启动

///

///

public bool setBoot()

{

RegistryKey loca = Registry.LocalMachine;

RegistryKey run = loca.CreateSubKey(@"SOFTWARE\Microsoft\Windows

\CurrentVersion\Run");

try

{

run.SetValue("QQ截图", appPath);

if (testBoot())

{

return true;

}

else

{

return false;

}

}

catch (Exception)

{

return false;

}

}

///

/// 取消启动

///

///

public bool cancelBoot()

{

RegistryKey loca = Registry.LocalMachine;

RegistryKey run = loca.CreateSubKey(@"SOFTWARE\Microsoft\Windows

\CurrentVersion\Run");

try

{

run.DeleteValue("QQ截图");

if (!testBoot())

{

return true;

}

else

{

return false;

}

}

catch (Exception)

{

return false;

}

}

///

/// 测试是否添加成功

///

///

private bool testBoot()

{

RegistryKey loca = Registry.LocalMachine;

RegistryKey run = loca.CreateSubKey(@"SOFTWARE\Microsoft\Windows

\CurrentVersion\Run");

string[] subkeyNames;

subkeyNames = run.GetValueNames();

foreach (string keyName in subkeyNames)

{

if (keyName == "QQ截图")

{

return true;

}

}

return false;

}

}

软件介绍

软件界面 image

我简单说一下使用

1:智能启用    软件可以检测QQ,如果QQ运行,则是使软件处于未启用状态,如果退出QQ,软件会自动启用。

2:当然如果不适用智能启用,你也可以手动启用

3:点击隐藏后,你可以在image中找到它,就是那个小剪刀

4:可以设置开机自动启动

5:使用快捷键和QQ一样  ctrl+alt+A

总结:设置开机启动和智能启用,你任何时候只要按ctrl+alt+A 就可以自己使用截图了

软件下载地址

[转载]eclipse+ADT 进行android应用签名详解

mikel阅读(895)

[转载]eclipse+ADT 进行android应用签名详解 – Jojol’s blog – ITeye技术网站.

1.Eclipse工程中右键工程,弹出选项中选择 Android工具-生成签名应用包:

2.选择需要打包的Android项目工程:

3.如果已有私钥文件,选择私钥文件 输入密码,如果没有私钥文件见 第6和7步创建私钥文件:

4.输入私钥别名和密码:

5.选择APK存储的位置,并完成设置 开始生成:

6.没有私钥文件的情况,创建私钥文件:

7.输入私钥文件所需信息,并创建:

[转载]Android UI设计 下拉菜单Spinner用法 动态添加删除Spinner菜单项

mikel阅读(984)

[转载]Android UI设计 下拉菜单Spinner用法 动态添加删除Spinner菜单项 | 应用开发笔记.

Spinner是一种下接菜单,类似HTML中的select标签,点击后弹出一个对话框,显示几个供选择的选项,手机屏幕大小有限,如果都用RadioGroup单选按钮,会占用很大的空间。今天的例子最终效果如下图:

Spinner需要绑定一个适配器ArrayAdapter,将菜单项放在适配器中,添加删除菜单项只需要调用适配器的add,remove方法即可。
布局XML;

<!--?xml version="1.0" encoding="utf-8"?-->
<button>
</button><button>

一个EditText,用于定义需要添加或删除的菜单项,一个添加,一个删除按钮,还有一个就是Spinner
在strings.xml中定义一个初始的数组,就是刚开始时Spinner显示的项目,当然,也可以直接在JAVA代码中定义:


吃饭
睡觉
上网

JAVA程序代码:

package com.pocketdigi.spanner;

import java.util.ArrayList;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

public class main extends Activity {
/** Called when the activity is first created. */
EditText et;
Button add,remove;
Spinner sp;
ArrayList list=new ArrayList();
ArrayAdapter adapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
et=(EditText)findViewById(R.id.et);
add=(Button)findViewById(R.id.add);
remove=(Button)findViewById(R.id.remove);
sp=(Spinner)findViewById(R.id.sp);
//获取相应对象
String[]  ls=getResources().getStringArray(R.array.action);
//获取XML中定义的数组
for(int i=0;i         	list.add(ls[i]);
}
//把数组导入到ArrayList中
adapter=new ArrayAdapter(this,android.R.layout.simple_spinner_item,list);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//设置下拉菜单的风格
sp.setAdapter(adapter);
//绑定适配器
sp.setPrompt("标题栏");
//设置对话框标题栏
add.setOnClickListener(new OnClickListener(){//添加按钮监听器

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
adapter.add(et.getText().toString());
//添加输入的项 ,add后自动调用notifyDataSetChanged()
//如果需要指定位置,使用insert(String s, int index)方法
setTitle(String.valueOf(list.size()));
//在标题输出添加后list的大小
}

});
remove.setOnClickListener(new OnClickListener(){//删除按钮监听器

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
adapter.remove(sp.getSelectedItem().toString());
//删除当前选中项,remove后自动调用notifyDataSetChanged()
setTitle(String.valueOf(list.size()));
}

});

}
}

源代码打包下载:
Spinner范例 (126)

[转载]Sql 2008查询优化-逻辑转换

mikel阅读(960)

[转载]Sql 2008查询优化-逻辑转换 – kevinLee – 博客园.

SQL 2008查询优化逻辑转换

SQL server 优化器在工作方式上,对or 逻辑处理在性能上存在问题,与 and 相比,性能差了些。为此,常看到SQL优化中,提到减少用or ,尽量用 and的说法。

在此,使用demo数据来验证此说法。“逻辑转换”,就是将逻辑or 转换成 and 的优化,主要分析逻辑筛选条件。

准备数据表:

1. 运行sql脚本生成order表,orderdata.txt

2.

IF OBJECT_ID(‘dbo.MyOrders’) IS NOT NULL

DROP TABLE dbo.MyOrders;

GO

SELECT * INTO dbo.MyOrders FROM Sales.Orders

CREATE INDEX idx_dt ON dbo.MyOrders(orderdate);

GO

3. 一切准备好后,假设筛选条件为:orderdate>’20080506’ or (orderdate=’20050506’ and ordered>11075)

运行下列语句:

SELECT orderid, orderdate, custid, empid

FROM dbo.MyOrders

WHERE orderdate > ‘20080506’

OR (orderdate = ‘20080506’ AND orderid > 11075);

其统计信息如下,

(2 行受影响)

‘MyOrders’。扫描计数1,逻辑读取20 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

(1 行受影响)

实际执行计划如下:

可以看出,这样的筛选条件,没有用上索引,而是执行表扫描。在现实中表的规模,将会是很大i/o开销。

分析逻辑条件,改为orderdate >= ‘20080506’ AND (orderdate > ‘20080506’ OR orderid > 11075) 即:

SELECT orderid, orderdate, custid, empid

FROM dbo.MyOrders

WHERE orderdate >= ‘20080506’

AND (orderdate > ‘20080506’ OR orderid > 11075);

统计信息以下:

(2 行受影响)

‘MyOrders’。扫描计数1,逻辑读取6 次,物理读取0 次,预读0 次,lob 逻辑读取0 次,lob 物理读取0 次,lob 预读0 次。

(1 行受影响)

实际执行计划如下:

可以看出,逻辑读只有6次,且用上了索引。如果在orderdateorderid上同时创建一个索引,性能会更好。

Ok,就到这了。

[转载]百度地图API交你如何用百度地图搜索自己的数据!不需数据库!

mikel阅读(940)

[转载]【百度地图API】交你如何用百度地图搜索自己的数据!不需数据库! – 酸奶小妹 – 博客园.

摘要:

我有一定的房产数据,还有银行数据。我想在百度地图上标注出来,并且能搜索到我这些数据。

可是百度的数据库上并没有我的数据。我应该怎么办呢?

——————————————————————————————

一、无需数据库,如何建立自己的地理信息表。

如果让初学者去建立数据库,那么意味着大家还要学习数据库,以及网站后端的知识。为了方便大家学习,使大家能够快速地掌握如何构建房产地图,银行地图等,酸奶小妹教大家一个“把数据存储在前端”,“搜索自己数据”的一个办法。(本文章要特别感谢不怕冷的小蚊子

首先,我们需要为自己的数据建立一个数组,把它们存储起来。像这样。

// 标注点数组
var BASEDATA = [
{title:"奥亚酒店",content:"北苑路169号",point:"116.422792|40.009471",isOpen:1,icon:{w:21,h:21,l:115,t:46,x:1,lb:10}},
{title:"珀丽酒店",content:"将台西路8号",point:"116.484289|39.97936",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"贵国酒店",content:"左家庄1号",point:"116.454494|39.964011",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"科通酒店",content:"民族园路8号院2号楼",point:"116.394601|39.987925",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"将台酒店",content:"酒仙桥路甲12号",point:"116.496024|39.976864",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"成宏酒店",content:"北四环东路惠新东桥西北侧",point:"116.429445|39.995392",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"华商酒店",content:"延静西里2号",point:"116.488962|39.921939",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"标华酒店",content:"北京市 朝阳区红庙路柴家湾1号",point:"116.489284|39.92104",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"万程酒店",content:"天坛路89号",point:"116.411762|39.89457",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"黎昌酒店",content:"永定门外彭庄乙58号",point:"116.393532|39.876272",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"北京银行",content:"北京市海淀区白石桥路39号",point:"116.329593|39.952398",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"海淀银行",content:"丹棱街16西门",point:"116.315551|39.984388",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"北京银行",content:"北京市西城区文津街附近",point:"116.391713|39.929007",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"首都银行",content:"东三环南路88号",point:"116.469899|39.87684",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"国家银行",content:"中关村南大街33号",point:"116.331292|39.949031",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"崇文区银行",content:"北京市崇文区花市大街113号(乐天玛特超市旁)的敕建火德真君庙内",point:"116.427671|39.903568",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"朝阳区银行",content:"北京市朝阳区朝外小庄金台里17号",point:"116.47766|39.922295",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"宣武区银行",content:"教子胡同8号",point:"116.374561|39.894302",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"东城区银行",content:"交道口东大街85号",point:"116.41927|39.9474",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"西城区银行",content:"北京市西城区后广平胡同26号",point:"116.368099|39.942332",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}}
]

意:这部分是写在js里的。

其中,title是信息窗口打开后的标题,同时也是label标签的取值;

content是信息窗口的内容;

point是经纬度,请使用百度坐标(获取地址:http://dev.baidu.com/wiki/static/map/API/tool/getPoint/);

isopen是控制信息窗口是否打开的开关;

icon里的选项是控制marker图片的,width是宽、hight是高等等。

二、如何查找,并显示自己的数据

你需要在html中写一个搜索框,一个搜索按钮。


<input id="keyword" style="width: 150px;" type="text" value="银行" />
<input onclick="search('type','show','keyword')" type="button" value="搜索" />

搜索框,需要一个id,例如keyword来传递要搜索的参数。我写了银行。本案例中,由于有酒店数据,你还可以写酒店。

搜索按钮,上面需要一个点击事件onclick=”search(‘type’,’show’,’keyword’)”。根据type类型、show是否显示、keyword关键词来做搜索。

那么,当搜索的内容,就是id=keyword里面的keyword和我自己的数据,就是步骤一里的数组,相同时,我就创建一个marker标注,并且默认打开它的信息窗口。

window.search = function(name_t,name_s,id_d){
var t_o = document.getElementsByName(name_t);
var s_o = document.getElementsByName(name_s);
var s_v,t_v,d_v = document.getElementById(id_d).value;
for(var i = 0; i &lt; t_o.length; i++){
if(t_o[i].checked){
t_v = t_o[i].value;
}
}
for(var i = 0; i &lt; s_o.length; i++){
if(s_o[i].checked){
s_v = s_o[i].value;
}
}
searchClass.trim(t_v) == "" &amp;&amp; (t_v = "single");
var dd = searchClass.search({k:"title",d:d_v,t:t_v,s:s_v});
addMarker(dd);//向地图中添加marker
}

三、全部源代码


为了更加符合用户的搜索习惯,我设计了精确超找、和模糊查找两种情况。

精确查找:就是用户输入的keyword,和我数据库里的一摸一样 时,就打开信息窗口。这时候一般只能打开一个。因为你自己的数据应该不会有重复的。

模糊查找:比如查找酒店,会显示全部的酒店。比如查找银行,会显示全部的银行数据。默认打开第一个的信息窗口。

为了方便大家看到我添加进去的数据信息,这里还设计了“仅查找到的内容”和“显示所有的内容”。

仅查找到的内容:用户搜什么,就显示出什么来。

显示所有的内容:显示我全部添加的数据。

全部源代码在这里,我减去了很多数据。大家可以自己添加。




自家数据+前端搜索
<script src="http://api.map.baidu.com/api?v=1.1&amp;services=true" type="text/javascript"></script>

二选一: <input id="type1" name="type" type="radio" value="single" /><label for="type1">精准查找</label> <input id="type2" checked="checked" name="type" type="radio" value="more" /><label for="type2">模糊查找</label> 二选一:  <input id="show1" checked="checked" name="show" type="radio" /><label for="show1">仅查找到的内容</label> <input id="show2" name="show" type="radio" value="all" /><label for="show2">显示所有内容</label> <input id="keyword" style="width: 150px;" type="text" value="银行" /> <input onclick="search('type','show','keyword')" type="button" value="搜索" />
 <script type="text/javascript">// <!&#91;CDATA&#91;
// 标注点数组
var BASEDATA = &#91;
{title:"奥亚酒店",content:"北苑路169号",point:"116.422792|40.009471",isOpen:1,icon:{w:21,h:21,l:115,t:46,x:1,lb:10}},
{title:"珀丽酒店",content:"将台西路8号",point:"116.484289|39.97936",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"北京银行",content:"北京市海淀区白石桥路39号",point:"116.329593|39.952398",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
{title:"海淀银行",content:"丹棱街16西门",point:"116.315551|39.984388",isOpen:0,icon:{w:21,h:21,l:0,t:0,x:6,lb:5}},
&#93;

//创建和初始化地图函数:
function initMap(){
window.map = new BMap.Map("container");
map.centerAndZoom(new BMap.Point(116.412318,39.887037),12);
map.enableScrollWheelZoom();
map.addControl(new BMap.NavigationControl());
window.searchClass = new SearchClass();
searchClass.setData(BASEDATA)
var dd = searchClass.search({k:"title",d:"银行",t:"more",s:""});//t:{single|more},s{all|!all}
addMarker(dd);//向地图中添加marker
}
window.search = function(name_t,name_s,id_d){
var t_o = document.getElementsByName(name_t);
var s_o = document.getElementsByName(name_s);
var s_v,t_v,d_v = document.getElementById(id_d).value;
for(var i = 0; i < t_o.length; i++){
if(t_o&#91;i&#93;.checked){
t_v = t_o&#91;i&#93;.value;
}
}
for(var i = 0; i < s_o.length; i++){
if(s_o&#91;i&#93;.checked){
s_v = s_o&#91;i&#93;.value;
}
}
searchClass.trim(t_v) == "" && (t_v = "single");
var dd = searchClass.search({k:"title",d:d_v,t:t_v,s:s_v});
addMarker(dd);//向地图中添加marker
}

//创建marker
window.addMarker = function (data){
map.clearOverlays();
for(var i=0;i<data.length;i++){
var json = data&#91;i&#93;;
var p0 = json.point.split("|")&#91;0&#93;;
var p1 = json.point.split("|")&#91;1&#93;;
var point = new BMap.Point(p0,p1);
var iconImg = createIcon(json.icon);
var marker = new BMap.Marker(point,{icon:iconImg});
var iw = createInfoWindow(i);
var label = new BMap.Label(json.title,{"offset":new BMap.Size(json.icon.lb-json.icon.x+10,-20)});
marker.setLabel(label);
map.addOverlay(marker);
label.setStyle({
borderColor:"#808080",
color:"#333",
cursor:"pointer"
});

(function(){
var _json = json;
var _iw = createInfoWindow(_json);
var _marker = marker;
_marker.addEventListener("click",function(){
this.openInfoWindow(_iw);
});
_iw.addEventListener("open",function(){
_marker.getLabel().hide();
})
_iw.addEventListener("close",function(){
_marker.getLabel().show();
})
label.addEventListener("click",function(){
_marker.openInfoWindow(_iw);
})
if(!!json.isOpen){
label.hide();
_marker.openInfoWindow(_iw);
}
})()
}
}
//创建InfoWindow
function createInfoWindow(json){
var iw = new BMap.InfoWindow("<b class='iw_poi_title' title='" + json.title + "'>" + json.title + "</b>
<div class='iw_poi_content'>"+json.content+"</div>
");
return iw;
}
//创建一个Icon
function createIcon(json){
var icon = new BMap.Icon("http://openapi.baidu.com/map/images/us_mk_icon.png", new BMap.Size(json.w,json.h),{imageOffset: new BMap.Size(-json.l,-json.t),infoWindowOffset:new BMap.Size(json.lb+5,1),offset:new BMap.Size(json.x,json.h)})
return icon;
}

function SearchClass(data){
this.datas = data;
}
// rule = {k:"title",d:"酒店",s:"all",t:"single"}=>t{single:(key=?),more:(key like&#91;%?%&#93;)}//t:{single|more},s{all|!all}
SearchClass.prototype.search = function(rule){
if(this.datas == null){alert("数据不存在!");return false;}
if(this.trim(rule) == "" || this.trim(rule.d) == "" || this.trim(rule.k) == "" || this.trim(rule.t) == ""){alert("请指定要搜索内容!");return false;}
var reval = &#91;&#93;;
var datas = this.datas;
var len = datas.length;
var me = this;
var ruleReg = new RegExp(this.trim(rule.d));
var hasOpen = false;

var addData = function(data,isOpen){
// 第一条数据打开信息窗口
if(isOpen && !hasOpen){
hasOpen = true;
data.isOpen = 1;
}else{
data.isOpen = 0;
}
reval.push(data);
}
var getData = function(data,key){
var ks = me.trim(key).split(/\./);
var i = null,s = "data";
if(ks.length == 0){
return data;
}else{
for(var i = 0; i < ks.length; i++){
s += '&#91;"' + ks&#91;i&#93; + '"&#93;';
}
return eval(s);
}
}
for(var cnt = 0; cnt < len; cnt++){
var data = datas&#91;cnt&#93;;
var d = getData(data,rule.k);
if(rule.t == "single" && rule.d == d){
addData(data,true);
}else if(rule.t != "single" && ruleReg.test(d)){
addData(data,true);
}else if(rule.s == "all"){
addData(data,false);
}
}
return reval;
}
SearchClass.prototype.setData = function(data){
this.datas = data;
}
SearchClass.prototype.trim = function(str){
if(str == null){str = "";}else{ str = str.toString();}
return str.replace(/(^&#91;\s\t\xa0\u3000&#93;+)|(&#91;\u3000\xa0\s\t&#93;+$)/g, "");
}

initMap();//创建和初始化地图
// &#93;&#93;></script>

四、示例运行请点击以下网址

http://dev.baidu.com/wiki/static/map/API/examples/?v=1.1&3_6#3&6

[转载]ASP.NET MVC3.0中使用JQuery的fancybox实现便签式留言板

mikel阅读(1067)

[转载]MVC3.0中使用JQuery的fancybox实现便签式留言板 – jackchain – 博客园.

采用JQuery的fancybox实现便签留言板。

关于fancybox的介绍请参看:http://tutorialzine.com/2010/01/sticky-notes-ajax-php-jquery/

demo:http://demo.tutorialzine.com/2010/01/sticky-notes-ajax-php-jquery/demo.php

照旧先看效果图:

关于fancybox的使用,我已经全封装到文件夹中了,看如何使用呢?

1.首先下载文件夹

http://files.cnblogs.com/qidian10/fancybox.rar

2.解压,放到你的项目中,然后修改文件styles.css,JQuery.fancybox-1.2.6.css,将里面的css图片路径换成你自己的路径

3.页面使用,新建一个cshtml页面,代码如下

@model IList<Model.customerheart>

@{
ViewBag.Title = "xxx";
Layout = "~/Views/Shared/_Layout.cshtml";
Random x = new Random(DateTime.Now.Millisecond);@*便签位置随机*@
}
@section head {
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  @*引用必要的库文件*@
<link rel="stylesheet" type="text/css" href="/Content/fancybox/styles.css" />
<link rel="stylesheet" type="text/css" href="/Content/fancybox/jquery.fancybox-1.2.6.css" media="screen" />
  <script src="/Scripts/jquery-1.4.4.min.js" type="text/javascript"></script>  
  <script src="/Scripts/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript" src="/Content/fancybox/jquery.fancybox-1.2.6.pack.js"></script>
<script type="text/javascript" src="/Content/fancybox/script.js" charset="uft-8"></script>
}

<div class="submain">
<div id="main">
<a id="addButton" class="green-button" href="/Content/fancybox/add_note.html">.我要评论.</a>
@foreach (Model.customerheart msg in Model)
{
<div class="note @msg.color" style="left:@x.Next(5,800)px; top:@x.Next(5,550)px; z-index:@x.Next(0,10)">
@msg.cheart
<div class="author">@msg.cname</div>
</div>
}
</div>
</div>

4.文件介绍

add_note.html:弹出层内容

script.js:所有的js操作(拖动),添加留言等

jQuery.fancybox.*:fancybox固定库,一般不需要改动。

[转载]android http post调用webservice

mikel阅读(1157)

[转载]android http post调用webservice – Android 开发|SDK下载|资料 – 乐致论坛 Android论坛_安卓论坛_Android软件_Android游戏_Android下载.

Android开发中如何执行一个Post请求。

首先我们先了解下Get请求和Post请求的区别:

表单提交中get和 post方式的区别有5点:
1.get是从服务器上获取数据,post是向服务器传送数据。
2.get是把参数数据队列加到提交表单的 ACTION属性所指的URL中,值和表单内各个字段一一对应,在URL中可以看到。post是通过HTTPpost机制,将表单内各个字段与其内容放置 在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。
3.对于get方式,服务器端用 Request.QueryString获取变量的值,对于post方式,服务器端用Request.Form获取提交的数据。
4.get 传送的数据量较小,不能大于2KB。post传送的数据量较大,一般被默认为不受限制。但理论上,IIS4中最大量为80KB,IIS5中为100KB。
5.get安全性非常低,post安全性较高。

那么接下来让我们看看在Android平台开发中如何执行一个Post请求:

以下是代码示例:

package com.jixuzou.search;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class mian extends Activity {
        /** Called when the activity is first created. */
        private Button btnTest;
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                btnTest = (Button) findViewById(R.id.Button01);
                btnTest.setOnClickListener(new OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                getWeather();
                        }
                });
        }
        private void getWeather(){
                try {
                        final String SERVER_URL = "http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx/getWeather"; // 定义需要获取的内容来源地址
                        HttpPost request = new HttpPost(SERVER_URL); // 根据内容来源地址创建一个Http请求
                        List params = new ArrayList();
                        params.add(new BasicNameValuePair("theCityCode", "长沙")); // 添加必须的参数
                        params.add(new BasicNameValuePair("theUserID", "")); // 添加必须的参数
                        request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8)); // 设置参数的编码
                        HttpResponse httpResponse = new DefaultHttpClient().execute(request); // 发送请求并获取反馈
                        // 解析返回的内容
                        if (httpResponse.getStatusLine().getStatusCode() != 404)
                        {
                                String result = EntityUtils.toString(httpResponse.getEntity());
                                System.out.println(result);
                        }
                } catch (Exception e) {
                }
        }
}

[转载]Android中SQLite操作示例

mikel阅读(1167)

[转载]Android中SQLite操作示例 – Android – mobile – ITeye论坛.

AndroidSQLite操作示例

Android中对SQLite数据库的操作,涉及以下几个方面:

1、确认数据库文件,即.db文件;

2、通过Android.database.sqlite. SQLiteDatabase类的openOrCreateDatabase()方法打开数据库;

3、数据库操作:

A、开始事务: SQLiteDatabase.beginTransaction();

B、执行sql语句;

C、结束事务: SQLiteDatabase.endTransaction();

具体代码可参考如下:

static boolean installDefaultSitesToDB(Context cxt) {
	// 确认目标数据库文件
	File path = cxt.getDir("databases", Context.MODE_WORLD_WRITEABLE);
	path = new File(path, "db_name.db");

	
	SQLiteDatabase db = null;
	try {
              // 打开数据库
              &nbsp;db = openDB(path.getAbsolutePath());
		if (db == null) {
			//Log.e("tag", "open db_name.db ERROR~");
			return false;
		}

		db.beginTransaction();//开始事务

                boolean bool = doInstallData(db);//执行sql语句,插入数据

               //设置事务标志
                if (bool) {
			db.setTransactionSuccessful();// 设置事务标志
		} else {
			//Log.w("tag", "doInstall.DEFAULT_SITES Fail~!");
		}
		return bool;
	} finally {
		if (db != null) {
                        //结束事务
			if (db.inTransaction()) {db.endTransaction();}
			db.close();
		}
	}
}

private static SQLiteDatabase openDB(String file) {
	try {
		//SQLiteDatabase.openOrCreateDatabase(file, null);
		int flag = SQLiteDatabase.OPEN_READWRITE;
		flag = flag | SQLiteDatabase.CREATE_IF_NECESSARY;
		flag = flag | SQLiteDatabase.NO_LOCALIZED_COLLATORS;
		SQLiteDatabase db = SQLiteDatabase.openDatabase(file, null, flag);
		return db;
	} catch (Throwable e) {
		//Log.e("tag","openDatabase error:" + e.getMessage());
		return null;
	}
}	

//
private static boolean doInstallData(SQLiteDatabase db) {
	try {
		//create table
		String sql = "CREATE TABLE IF NOT EXISTS Permissions (origin TEXT UNIQUE NOT NULL, allow INTEGER NOT NULL)";
		db.execSQL(sql);
		
		ContentValues cv = new ContentValues();
		for (String site : DEFAULT_SITES) {
			cv.clear();
			cv.put("origin", site);
			cv.put("allow", 1);
			long ret = 	db.insertOrThrow("Permissions", null, cv);
			Log.d("tag", "db.insert.RET:" + ret);
		}
		return true;
	} catch (SQLException se) {
		String msg = "doInstall.error:[%s].%s";
		Log.d("tag",String.format(msg, se.getClass(),se.getMessage()));
		return false;
	}
}